Refreshing a folder that doesn't exist in the file system

偶尔善良 提交于 2019-12-25 04:12:17

问题


In my shell extension I have folders that don't actually exist in the file system, but only appear so to the user.

When the content of those folders is changed, I want to refresh them, and currently I do it in the same method I do for regular folders:

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

Whereas PIDL is a list of shell folders IDs, as required by SHCNF_IDLIST.

The problem is that explorer doesn't handle my non existing folders. Instead of refreshing them, it sends me back to the root folder.

I know that I construct the PIDL correctly since this mechanism works for existing folders, as previously mentioned.

How can I override the handler to SHChangeNotify? Or is there a better way for calling refresh?

Edit:

How my PIDL is generated:

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

My CreatePIDL implementation:

        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:


I found a workaround. It is not pretty nor optimal, yet it works well.

Instead of calling the notify with SHCNE_UPDATEDIR, I'm executing all three of the following notifiers in sequence:

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


来源:https://stackoverflow.com/questions/29004302/refreshing-a-folder-that-doesnt-exist-in-the-file-system

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!