如何获取开放资源管理器窗口的PIDL?

Ste*_*ris 3 c# com winapi windows-explorer

我知道如何使用Microsoft Internet Controls COM库获取所有打开的资源管理器窗口.从这里,我能够找到LocationURL那些窗户.但是,这仅针对文件系统上的路径设置.似乎何时显示虚拟对象(如网络打印机或回收站)LocationURL为空.LocationName仍然似乎设置为开始栏上可见的名称.

LocationURL设置何时,这足以让我知道资源管理器窗口指向的位置,但是如何找到这些特殊文件夹指向的内容?

读取指向项目标识符列表(PIDL)的指针.知道在资源管理器窗口中显示哪个PIDL可以识别出这一点.有没有办法检索这个?

Sim*_*ier 8

下面是一个示例C#Console应用程序代码,它获取当前Windows资源管理器窗口的PIDL:

class Program
{
    static void Main(string[] args)
    {
        var shellWindows = new ShellWindows();
        foreach (IWebBrowser2 win in shellWindows)
        {
            IServiceProvider sp = win as IServiceProvider;
            object sb;
            sp.QueryService(SID_STopLevelBrowser, typeof(IShellBrowser).GUID, out sb);
            IShellBrowser shellBrowser = (IShellBrowser)sb;
            object sv;
            shellBrowser.QueryActiveShellView(out sv);
            Console.WriteLine(win.LocationURL + " " + win.LocationName);
            IFolderView fv = sv as IFolderView;
            if (fv != null)
            {
                // only folder implementation support this (IE windows do not for example)
                object pf;
                fv.GetFolder(typeof(IPersistFolder2).GUID, out pf);
                IPersistFolder2 persistFolder = (IPersistFolder2)pf;

                // get folder class, for example
                // CLSID_ShellFSFolder for standard explorer folders
                Guid clsid;
                persistFolder.GetClassID(out clsid);
                Console.WriteLine(" clsid:" + clsid);

                // get current folder pidl
                IntPtr pidl;
                persistFolder.GetCurFolder(out pidl);

                // TODO: do something with pidl

                Marshal.FreeCoTaskMem(pidl); // free pidl's allocated memory
            }
        }
    }

    internal static readonly Guid SID_STopLevelBrowser = new Guid(0x4C96BE40, 0x915C, 0x11CF, 0x99, 0xD3, 0x00, 0xAA, 0x00, 0x4A, 0xE8, 0x37);

    [InterfaceType(ComInterfaceType.InterfaceIsIUnknown), Guid("6D5140C1-7436-11CE-8034-00AA006009FA")]
    internal interface IServiceProvider
    {
        void QueryService([MarshalAs(UnmanagedType.LPStruct)] Guid guidService, [MarshalAs(UnmanagedType.LPStruct)] Guid riid, [MarshalAs(UnmanagedType.IUnknown)] out object ppvObject);
    }

    [InterfaceType(ComInterfaceType.InterfaceIsIUnknown), Guid("1AC3D9F0-175C-11d1-95BE-00609797EA4F")]
    internal interface IPersistFolder2
    {
        void GetClassID(out Guid pClassID);
        void Initialize(IntPtr pidl);
        void GetCurFolder(out IntPtr pidl);
    }

    [InterfaceType(ComInterfaceType.InterfaceIsIUnknown), Guid("000214E2-0000-0000-C000-000000000046")]
    internal interface IShellBrowser
    {
        void _VtblGap0_12(); // skip 12 members
        void QueryActiveShellView([MarshalAs(UnmanagedType.IUnknown)] out object ppshv);
        // the rest is not defined
    }

    [InterfaceType(ComInterfaceType.InterfaceIsIUnknown), Guid("cde725b0-ccc9-4519-917e-325d72fab4ce")]
    internal interface IFolderView
    {
        void _VtblGap0_2(); // skip 2 members
        void GetFolder([MarshalAs(UnmanagedType.LPStruct)] Guid riid, [MarshalAs(UnmanagedType.IUnknown)] out object ppv);
        // the rest is not defined
    }
}
Run Code Online (Sandbox Code Playgroud)

注意:Shell接口仅部分定义,因为我们不需要完整的详细信息.如果您需要其他信息,请随时填写.

  • 是的。COM 和 .NET 之间存在很大的混淆。相同的名称,相同的用途,100% 不同:-) Shell COM 库是为自动化兼容客户端(VB/VBA、脚本语言等)而设计的。无论如何,这些客户端无法访问纯 IUnknown(不是 IDispatch)接口。.NET 更强大并且可以使用它,但我认为没有任何 TLB 可用于我们可以导入的这些接口。请注意,Windows API 代码包中定义了许多接口:http://archive.msdn.microsoft.com/WindowsAPICodePack (2认同)