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



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

当这些文件夹的内容发生更改时,我想刷新它们,目前我以与常规文件夹相同的方法执行此操作:

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

PIDL 是 shell 文件夹 ID 的列表,如 SHCNF_IDLIST 的要求。

问题是资源管理器不处理我的非现有文件夹。它不会刷新它们,而是将我发送回根文件夹。

我知道我正确地构造了PIDL,因为如前所述,此机制适用于现有文件夹。

如何覆盖处理程序以SHChangeNotify?或者有没有更好的方法来调用刷新?

编辑:

我的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;
        }

我找到了解决方法。它既不漂亮也不理想,但它运作良好。

我不是用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);

最新更新