0

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

1 回答 1

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);
于 2015-03-18T14:37:52.133 回答