0

Dans mon extension shell, j'ai des dossiers qui n'existent pas dans le système de fichiers, mais n'apparaissent que pour l'utilisateur.Actualisation d'un dossier qui n'existe pas dans le système de fichiers

Lorsque le contenu de ces dossiers est changé, je veux les rafraîchir, et actuellement je le fais dans la même méthode que je fais pour les dossiers réguliers:

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

Alors PIDL est une liste d'ID de dossiers shell , comme requis par SHCNF_IDLIST.

Le problème est que l'explorateur ne gère pas mes dossiers non existants. Au lieu de les rafraîchir, cela me renvoie au dossier racine.

Je sais que je construis correctement le PIDL puisque ce mécanisme fonctionne pour les dossiers existants, comme mentionné précédemment. Comment puis-je remplacer le gestionnaire par SHChangeNotify? Ou y a-t-il un meilleur moyen d'appeler l'actualisation?

Edit:

Comment mon PIDL est généré:

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); 
    } 

Mon CreatePIDL mise en œuvre:

 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

La documentation à https://msdn.microsoft.com/en-us/library/ windows/desktop/bb762118% 28v = vs.85% 29.aspx indique que lors de l'appel de SHCNE_UPDATEDIR, le répertoire doit exister. – Mugen

+0

Quelque chose ne va pas avec votre code. J'utilise SHChangeNotify (SHCNE_UPDATEDIR, SHCNF_IDLIST) pour mettre à jour mes dossiers d'espaces de noms virtuels et cela fonctionne. Pourriez-vous expliquer le terme "PIDL est une liste d'ID de dossiers shell"? –

+0

@DenisAnisimov Mon but est de rafraîchir un dossier donné. Est-ce que ma liste ne contient que le dossier que je veux actualiser? Actuellement, je renvoie une liste de PIDL du répertoire courant et de son parent jusqu'à la racine. Pour obtenir le PIDL d'un élément de dossier donné (qui implémente IShellFolder et IShellFolder2), j'utilise simplement la classe Marshal. – Mugen

Répondre

0

Je trouve une solution de contournement. Ce n'est pas joli ni optimal, mais ça marche bien.

Au lieu d'appeler notify avec SHCNE_UPDATEDIR, j'exécuter les trois suivantes notifiants en séquence:

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);