代码之家  ›  专栏  ›  技术社区  ›  Mugen

刷新文件系统中不存在的文件夹

  •  0
  • Mugen  · 技术社区  · 11 年前

    在我的shell扩展中,我的文件夹实际上并不存在于文件系统中,但只对用户显示。

    当这些文件夹的内容发生更改时,我想刷新它们,目前我使用的方法与普通文件夹相同:

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

    鉴于 PIDL 是shell文件夹ID的列表,如所需 SHCNF_IDLIST .

    问题是资源管理器无法处理我不存在的文件夹。它没有刷新它们,而是将我送回根文件夹。

    我知道我构建了 皮德尔牌手表 正确,因为如前所述,此机制适用于现有文件夹。

    如何将处理程序重写为 SHChangeNotify ? 还是有更好的方法调用刷新?

    编辑:

    我的 皮德尔牌手表 生成:

        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;
            }
    
    1 回复  |  直到 11 年前
        1
  •  0
  •   Mugen    11 年前

    我找到了一个解决方法。它既不漂亮,也不是最佳的,但它工作得很好。

    而不是使用 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);
    
    推荐文章