0

В моем расширении оболочки у меня есть папки, которые фактически не существуют в файловой системе, но отображаются только для пользователя.Обновление папки, которая не существует в файловой системе

Когда содержание этих папок изменяется, я хочу, чтобы обновить их, и в настоящее время я делаю это в тот же метод, что я делаю для обычных папок:

Win32.SHChangeNotify(SHCNE_UPDATEDIR, SHCNF_IDLIST | SHCNF_FLUSH, PIDL, IntPtr.Zero); 

Принимая во внимание PIDL список идентификаторов папок оболочки , как требуется SHCNF_IDLIST.

Проблема в том, что исследователь не обрабатывает мои несуществующие папки. Вместо того, чтобы обновлять их, он отправляет меня обратно в корневую папку.

Я знаю, что правильно строю PIDL, так как этот механизм работает для существующих папок, как упоминалось ранее.

Как я могу переопределить обработчик на SHChangeNotify? Или есть лучший способ для вызова обновления?

Edit:

Как мой PIDL генерируется:

IntPtr GetPIDL(IFolderItem target) 
    { 
     Stack stack = new Stack(5); 
     IntPtr data = IntPtr.Zero; 

     byte[] rootPIDL = null; 

     IFolderItem curr = target; 
     while (curr != null) 
     { 
      if (curr.rootPIDL != null) 
      { 
       rootPIDL = curr.rootPIDL; 
      } 
      else 
      { 
       data = curr.SerializeInt(); 
       stack.Push(data); 
      } 

      curr = curr.ParentFolder; 
     } 

     if (rootPIDL == null && stack.Count == 0) 
      return IntPtr.Zero; 

     object[] x = stack.ToArray(); 

     IntPtr[] pidls = null; 

     int count = stack.Count; 
     if (count > 0) 
     { 
      pidls = new IntPtr[stack.Count]; 
      for (int i = 0; i < count; i++) 
      { 
       pidls[i] = (IntPtr)stack.Pop(); 
      } 
     } 

     return CreatePIDL(rootPIDL, pidls); 
    } 

CreatePIDL Моя реализация:

 internal unsafe static IntPtr CreatePIDL(byte[] rootPIDL,IntPtr[] pidls) 
     { 
      int headerSize = Marshal.SizeOf(typeof(ushort)); 
      int totalSize = headerSize; 
      if (rootPIDL != null) 
       totalSize += rootPIDL.Length - headerSize; 

      if (pidls!=null && pidls.Length > 0) 
      { 
       foreach (IntPtr data in pidls) 
       { 
        totalSize += PIDLSize(data); 
       } 
      } 

      IntPtr ret = PIDLAlloc(totalSize); 
      IntPtr currPos = ret; 

      if(rootPIDL!=null) 
      { 
       Marshal.Copy(rootPIDL, 0, currPos, rootLPIFQ.Length - headerSize); 
       currPos = Win32.AdvancePtr(currPos, rootLPIFQ.Length - headerSize); 
      } 

      if (pidls != null && pidls.Length>0) 
      { 
       foreach (IntPtr data in pidls) 
       { 
        int dataLength = PIDLSize(data); 
        Win32.CopyMemory(currPos, data, dataLength); 
        currPos = Win32.AdvancePtr(currPos, dataLength); 
       } 
      } 
      Marshal.WriteInt16(currPos, (short)0); 

      return ret; 
     } 

     internal static unsafe int PIDLSize(IntPtr ptr) 
     { 
      return (int) (*((ushort*)ptr)); 
     } 

     internal unsafe static IntPtr PIDLAlloc(int size) 
     { 
      IntPtr ret = Marshal.AllocCoTaskMem(size); 
      if (ret == IntPtr.Zero) 
       throw new OutOfMemoryException(); 

      return ret; 
     } 
+0

документации на https://msdn.microsoft.com/en-us/library/ windows/desktop/bb762118% 28v = vs.85% 29.aspx заявляет, что при вызове SHCNE_UPDATEDIR каталог должен существовать. – Mugen

+0

Что-то не так с вашим кодом. Я использую SHChangeNotify (SHCNE_UPDATEDIR, SHCNF_IDLIST) для обновления моих виртуальных папок пространства имен, и он работает. Не могли бы вы объяснить термин «PIDL - это список идентификаторов папок оболочки»? –

+0

@DenisAnisimov Моя цель - обновить заданную папку. Должен ли мой список содержать только папку, которую я хочу обновить? В настоящее время я возвращаю список PIDL из текущего каталога и его родителя до корня. Чтобы получить PIDL данного элемента папки (который реализует IShellFolder и IShellFolder2), я просто использую класс маршала. – Mugen

ответ

0

Я нашел обходной путь. Это не очень и не оптимально, но он работает хорошо.

Вместо вызова оповещать SHCNE_UPDATEDIR, я выполнение все три из следующих уведомителей в последовательности:

Win32.SHChangeNotify(SHCNE_MKDIR, SHCNF_IDLIST | SHCNF_FLUSH, PIDL, IntPtr.Zero); 
Win32.SHChangeNotify(SHCNE_CREATE, SHCNF_IDLIST | SHCNF_FLUSH, PIDL, IntPtr.Zero); 
Win32.SHChangeNotify(SHCNE_ASSOCCHANGED, SHCNF_IDLIST | SHCNF_FLUSH, PIDL, IntPtr.Zero);