【问题标题】:Get selected files from Desktop从桌面获取选定的文件
【发布时间】:2020-06-28 20:01:48
【问题描述】:

我正在尝试从桌面获取选定文件的列表。我得到了正确数量的文件,但我得到了像这样的奇怪文件名,例如:㺘䁐\u0086\u0002。我正在使用LVM_GETITEM message 来获取信息。这是我的代码:

        public string GetItemText(int idx)
        {
            const int MAX_SIZE = 512;
            byte[] szBuffer = new byte[MAX_SIZE];

            LVITEM lvi = new LVITEM
            {
                mask = LVIF_TEXT,
                cchTextMax = MAX_SIZE,
                iItem = idx,
                iSubItem = 0,
                pszText = Marshal.AllocHGlobal(MAX_SIZE)
            };

            // Fill LVITEM structure
            IntPtr ptrLvi = Marshal.AllocHGlobal(Marshal.SizeOf(lvi));
            Marshal.StructureToPtr(lvi, ptrLvi, false);
            int readBytes = 0;
            try
            {
                readBytes = SendMessagePtr(ShellListViewHandle, LVM_GETITEM, IntPtr.Zero, ptrLvi);
            }
            catch (Exception ex)
            {
                System.Diagnostics.Debug.WriteLine(ex.Message);
            }

            // Get the text
            string itemText = Marshal.PtrToStringAuto(lvi.pszText);
            return itemText;
        }

【问题讨论】:

  • 行不通。您需要在资源管理器进程中分配内存。但是,你为什么要黑客攻击。难道没有shell接口可以做到这一点吗?
  • 请注意“从桌面获取选定文件列表”的确切含义。如果您的意思是从桌面上打开的视图中获取所选项目的列表,您可以使用 C# 中的 Shell API docs.microsoft.com/en-us/windows/win32/shell/… 和示例:stackoverflow.com/questions/8292953/…
  • 不,我的意思是当我选择一些文件时,就在我的桌面上。单击其中一个文件,例如 howtogeek.com/wp-content/uploads/2018/08/img_5b6e4770e6897.jpg
  • 我相信你也可以从 shell api 做到这一点。在我看来,尝试破解桌面的特定实现是一个错误。除此之外,您编码失败的原因是您提供了在错误进程中分配的内存。
  • 您有如何使用 Shell API 的代码示例吗?如果这更容易,那就太好了。

标签: c# winapi


【解决方案1】:

您无法使用Shell Objects for Scripting AFAIK 做到这一点。您只能从它开始,然后使用本机 Shell 接口。

此原则在 C/C++ 中的 Manipulating the positions of desktop icons 中进行了解释。

这是一个类似的 C# 控制台应用程序,它会转储当前在桌面中选择的所有项目名称,您必须根据需要进行调整或扩展:

public class Program
{
    static void Main()
    {
        // we basically follow https://devblogs.microsoft.com/oldnewthing/20130318-00/?p=4933
        dynamic app = Activator.CreateInstance(Type.GetTypeFromProgID("Shell.Application"));
        var windows = app.Windows;

        const int SWC_DESKTOP = 8;
        const int SWFO_NEEDDISPATCH = 1;
        var hwnd = 0;
        var disp = windows.FindWindowSW(Type.Missing, Type.Missing, SWC_DESKTOP, ref hwnd, SWFO_NEEDDISPATCH);

        var sp = (IServiceProvider)disp;
        var SID_STopLevelBrowser = new Guid("4c96be40-915c-11cf-99d3-00aa004ae837");

        var browser = (IShellBrowser)sp.QueryService(SID_STopLevelBrowser, typeof(IShellBrowser).GUID);
        var view = (IFolderView)browser.QueryActiveShellView();

        view.Items(SVGIO.SVGIO_SELECTION, typeof(IShellItemArray).GUID, out var items);
        if (items is IShellItemArray array)
        {
            for (var i = 0; i < array.GetCount(); i++)
            {
                var item = array.GetItemAt(i);
                Console.WriteLine(item.GetDisplayName(SIGDN.SIGDN_NORMALDISPLAY));
            }
        }
    }

    [Guid("6D5140C1-7436-11CE-8034-00AA006009FA"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
    private interface IServiceProvider
    {
        [return: MarshalAs(UnmanagedType.IUnknown)]
        object QueryService([MarshalAs(UnmanagedType.LPStruct)] Guid service, [MarshalAs(UnmanagedType.LPStruct)] Guid riid);
    }

    // note: for the following interfaces, not all methods are defined as we don't use them here
    [Guid("000214E2-0000-0000-C000-000000000046"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
    private interface IShellBrowser
    {
        void _VtblGap1_12(); // skip 12 methods https://stackoverflow.com/a/47567206/403671

        [return: MarshalAs(UnmanagedType.IUnknown)]
        object QueryActiveShellView();
    }

    [Guid("cde725b0-ccc9-4519-917e-325d72fab4ce"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
    private interface IFolderView
    {
        void _VtblGap1_5(); // skip 5 methods

        [PreserveSig]
        int Items(SVGIO uFlags, Guid riid, [MarshalAs(UnmanagedType.IUnknown)] out object items);
    }

    [Guid("43826d1e-e718-42ee-bc55-a1e261c37bfe"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
    private interface IShellItem
    {
        [return: MarshalAs(UnmanagedType.IUnknown)]
        object BindToHandler(System.Runtime.InteropServices.ComTypes.IBindCtx pbc, [MarshalAs(UnmanagedType.LPStruct)] Guid bhid, [MarshalAs(UnmanagedType.LPStruct)] Guid riid);

        IShellItem GetParent();

        [return: MarshalAs(UnmanagedType.LPWStr)]
        string GetDisplayName(SIGDN sigdnName);

        // 2 other methods to be defined
    }

    [Guid("b63ea76d-1f85-456f-a19c-48159efa858b"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
    private interface IShellItemArray
    {
        void _VtblGap1_4(); // skip 4 methods

        int GetCount();
        IShellItem GetItemAt(int dwIndex);
    }

    private enum SIGDN
    {
        SIGDN_NORMALDISPLAY,
        SIGDN_PARENTRELATIVEPARSING,
        SIGDN_DESKTOPABSOLUTEPARSING,
        SIGDN_PARENTRELATIVEEDITING,
        SIGDN_DESKTOPABSOLUTEEDITING,
        SIGDN_FILESYSPATH,
        SIGDN_URL,
        SIGDN_PARENTRELATIVEFORADDRESSBAR,
        SIGDN_PARENTRELATIVE,
        SIGDN_PARENTRELATIVEFORUI
    }

    private enum SVGIO
    {
        SVGIO_BACKGROUND,
        SVGIO_SELECTION,
        SVGIO_ALLVIEW,
        SVGIO_CHECKED,
        SVGIO_TYPE_MASK,
        SVGIO_FLAG_VIEWORDER
    }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-04-16
    • 1970-01-01
    • 2020-08-30
    • 2017-03-27
    相关资源
    最近更新 更多