代码之家  ›  专栏  ›  技术社区  ›  Orion Edwards

在Windows资源管理器中以编程方式选择多个文件

  •  18
  • Orion Edwards  · 技术社区  · 16 年前

    我可以这样在Windows资源管理器中显示和选择单个文件:

    explorer.exe /select, "c:\path\to\file.txt"
    

    但是,我无法确定如何选择多个文件。我试过的所有选择排列都没有。

    注意:我在这些页面上查看了文档,没有任何帮助。

    https://support.microsoft.com/kb/314853
    http://www.infocellar.com/Win98/explorer-switches.htm

    7 回复  |  直到 7 年前
        1
  •  17
  •   flashk    14 年前

    这应该可以通过shell函数实现。 SHOpenFolderAndSelectItems

    编辑

    这里有一些示例代码,说明如何在C/C++中使用该函数,而无需错误检查:

    //Directory to open
    ITEMIDLIST *dir = ILCreateFromPath(_T("C:\\"));
    
    //Items in directory to select
    ITEMIDLIST *item1 = ILCreateFromPath(_T("C:\\Program Files\\"));
    ITEMIDLIST *item2 = ILCreateFromPath(_T("C:\\Windows\\"));
    const ITEMIDLIST* selection[] = {item1,item2};
    UINT count = sizeof(selection) / sizeof(ITEMIDLIST);
    
    //Perform selection
    SHOpenFolderAndSelectItems(dir, count, selection, 0);
    
    //Free resources
    ILFree(dir);
    ILFree(item1);
    ILFree(item2);
    
        2
  •  5
  •   Siarhei Kuchuk    14 年前

    在资源管理器中选择多个文件的真正方法是

    非托管代码看起来是这样的(从中国的代码文章中编译,并修复其错误)

    static class NativeMethods
    {
        [DllImport("shell32.dll", ExactSpelling = true)]
        public static extern int SHOpenFolderAndSelectItems(
            IntPtr pidlFolder,
            uint cidl,
            [In, MarshalAs(UnmanagedType.LPArray)] IntPtr[] apidl,
            uint dwFlags);
    
        [DllImport("shell32.dll", CharSet = CharSet.Auto)]
        public static extern IntPtr ILCreateFromPath([MarshalAs(UnmanagedType.LPTStr)] string pszPath);
    
        [ComImport]
        [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
        [Guid("000214F9-0000-0000-C000-000000000046")]
        public interface IShellLinkW
        {
            [PreserveSig]
            int GetPath(StringBuilder pszFile, int cch, [In, Out] ref WIN32_FIND_DATAW pfd, uint fFlags);
    
            [PreserveSig]
            int GetIDList([Out] out IntPtr ppidl);
    
            [PreserveSig]
            int SetIDList([In] ref IntPtr pidl);
    
            [PreserveSig]
            int GetDescription(StringBuilder pszName, int cch);
    
            [PreserveSig]
            int SetDescription([MarshalAs(UnmanagedType.LPWStr)] string pszName);
    
            [PreserveSig]
            int GetWorkingDirectory(StringBuilder pszDir, int cch);
    
            [PreserveSig]
            int SetWorkingDirectory([MarshalAs(UnmanagedType.LPWStr)] string pszDir);
    
            [PreserveSig]
            int GetArguments(StringBuilder pszArgs, int cch);
    
            [PreserveSig]
            int SetArguments([MarshalAs(UnmanagedType.LPWStr)] string pszArgs);
    
            [PreserveSig]
            int GetHotkey([Out] out ushort pwHotkey);
    
            [PreserveSig]
            int SetHotkey(ushort wHotkey);
    
            [PreserveSig]
            int GetShowCmd([Out] out int piShowCmd);
    
            [PreserveSig]
            int SetShowCmd(int iShowCmd);
    
            [PreserveSig]
            int GetIconLocation(StringBuilder pszIconPath, int cch, [Out] out int piIcon);
    
            [PreserveSig]
            int SetIconLocation([MarshalAs(UnmanagedType.LPWStr)] string pszIconPath, int iIcon);
    
            [PreserveSig]
            int SetRelativePath([MarshalAs(UnmanagedType.LPWStr)] string pszPathRel, uint dwReserved);
    
            [PreserveSig]
            int Resolve(IntPtr hwnd, uint fFlags);
    
            [PreserveSig]
            int SetPath([MarshalAs(UnmanagedType.LPWStr)] string pszFile);
        }
    
        [Serializable, StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode), BestFitMapping(false)]
        public struct WIN32_FIND_DATAW
        {
            public uint dwFileAttributes;
            public FILETIME ftCreationTime;
            public FILETIME ftLastAccessTime;
            public FILETIME ftLastWriteTime;
            public uint nFileSizeHigh;
            public uint nFileSizeLow;
            public uint dwReserved0;
            public uint dwReserved1;
    
            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 260)]
            public string cFileName;
    
            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 14)]
            public string cAlternateFileName;
        }
    
        public static void OpenFolderAndSelectFiles(string folder, params string[] filesToSelect)
        {
            IntPtr dir = ILCreateFromPath(folder);
    
            var filesToSelectIntPtrs = new IntPtr[filesToSelect.Length];
            for (int i = 0; i < filesToSelect.Length; i++)
            {
                filesToSelectIntPtrs[i] = ILCreateFromPath(filesToSelect[i]);
            }
    
            SHOpenFolderAndSelectItems(dir, (uint) filesToSelect.Length, filesToSelectIntPtrs, 0);
            ReleaseComObject(dir);
            ReleaseComObject(filesToSelectIntPtrs);
        }
    
        private static void ReleaseComObject(params object[] comObjs)
        {
            foreach (object obj in comObjs)
            {
                if (obj != null && Marshal.IsComObject(obj))
                    Marshal.ReleaseComObject(obj);
            }
        }
    }
    
        3
  •  2
  •   Nick Berardi    16 年前

    不能通过explorer.exe完成

        4
  •  1
  •   bruceatk    16 年前

    取决于你真正想要完成的是什么,你也许能够做到这一点。 AutoHotKey . 它是一个神奇的免费工具,可以自动完成你通常做不到的事情。它应该有窗户。当您点击F12时,这个脚本将选择您的文件并突出显示它下面的两个文件。

    F12:: 
     run explorer.exe /select`, "c:\path\to\file.txt"
     SendInput {Shift Down}{Down}{Down}{Shift Up}
    return
    

    也可以将这两个中间行放在文本文件中,然后将parm传递给autohotkey.exe。他们还可以选择编译脚本,这将使它成为一个独立的可调用的exe。很好的帮助文件。

    @猎户座,可以使用C的自动热键。您可以将autohotkey脚本制作成一个独立的可执行文件(大约400K),它可以由您的C应用程序启动(就像启动Explorer一样)。还可以传递命令行参数。它没有任何运行时要求。

        5
  •  1
  •   Orion Edwards    15 年前

    这是其中一个问题,在这里考虑你想要达到的目标,以及是否有更好的方法是很好的。

    添加更多上下文- 我们公司开发了一个C客户端应用程序,它允许用户加载文件并使用它们做一些事情,类似于iTunes如何管理MP3文件而不显示磁盘上的实际文件。

    在应用程序中选择一个文件,并执行“在Windows资源管理器中显示此文件”命令非常有用-这是我正在尝试实现的,并且对单个文件也是如此。

    我们有一个列表视图,允许用户在应用程序中选择多个文件,并移动/删除/等等。让这个“在Windows中显示这个文件”命令用于多个选定的文件是很好的—至少如果所有源文件都在同一目录中,但是如果不可能,那么它不是一个主要功能。

        6
  •  0
  •   PhiLho    16 年前

    我想你可以用 FindWindowEx 要获取Windows资源管理器的SysListView32,请使用 SendMessage 具有 LVM_SETITEMSTATE 选择项目。很难知道物品的位置…也许 LVM_FINDITEM 可以用来做这个。

        7
  •  0
  •   Brad    16 年前

    我也想这么做。当您选择2+个文件并右键单击并执行“打开文件位置”时,Media Player会执行此操作,但不确定具体的方式(我也不想花时间w/procmon来解决此问题)。