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

时间:2023-01-17 08:44:29

I can display and select a single file in windows explorer like this:

我可以在Windows资源管理器中显示和选择单个文件,如下所示:

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

However, I can't work out how to select more than one file. None of the permutations of select I've tried work.

但是,我无法弄清楚如何选择多个文件。没有选择的排列我尝试过工作。

Note: I looked at these pages for docs, neither helped.

注意:我查看了这些页面的文档,但没有帮助。

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

7 个解决方案

#1


17  

This should be possible with the shell function SHOpenFolderAndSelectItems

这应该可以使用shell函数SHOpenFolderAndSelectItems

EDIT

Here is some sample code showing how to use the function in C/C++, without error checking:

下面是一些示例代码,展示了如何在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  

The true way of selecting multiple files in Explorer is the next

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

Unmanaged code looks like this (compiled from China code posts with fixing its bugs)

非托管代码看起来像这样(从中国代码帖子编译修复其错误)

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  

it cannot be done through explorer.exe

它无法通过explorer.exe完成

#4


1  

Depending on what you actually want to accomplish you may be able to do it with AutoHotKey. It is an amazing free tool for automating things you normally can't do. It should come with Windows. This script will select your file and highlight the next two files below it when you hit F12.

根据您实际想要实现的目标,您可以使用AutoHotKey进行操作。它是一个惊人的免费工具,可以自动执行您通常无法做的事情。它应该与Windows一起提供。当您点击F12时,此脚本将选择您的文件并突出显示其下面的下两个文件。

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

It is also possible to just put those two middle lines in a text file and then pass it is a parm to autohotkey.exe. They have an option to compile the script also, which would make it a standalone exe that you could call. Works great with a great help file.

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

@Orion, It is possible to use autohotkey from C#. You can make an autohotkey script into a standalone executable (about 400k) that can be launched by your C# app (just the way you are launching explorer). You can also pass it command line parameters. It does not have any runtime requirements.

@Orion,可以使用C#中的autohotkey。您可以将autohotkey脚本创建为可以由C#app启动的独立可执行文件(大约400k)(就像启动资源管理器一样)。您也可以传递命令行参数。它没有任何运行时要求。

#5


1  

This is one of those questions where it may be good to consider what you're trying to achieve, and whether there's a better method.

这是一个问题,其中可能很好地考虑你想要实现的目标,以及是否有更好的方法。

To add some more context - Our company develops a C# client application, which allows users to load files and do stuff with them, kind of like how iTunes manages your MP3 files without showing you the actual file on disk.

添加更多上下文 - 我们公司开发了一个C#客户端应用程序,它允许用户加载文件并使用它们进行操作,有点像iTunes管理MP3文件而不向您显示磁盘上的实际文件。

It's useful to select a file in the application, and do a 'Show me this file in Windows Explorer` command - this is what I'm trying to achieve, and have done so for single files.

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

We have a ListView which allows users to select multiple files within the application, and move/delete/etc them. It would be nice to have this 'show me this file in windows' command work for multiple selected files - at least if all the source files are in the same directory, but if it's not possible then it's not a major feature.

我们有一个ListView,允许用户在应用程序中选择多个文件,并移动/删除/等等。如果所有的源文件都在同一个目录中,至少如果所有的源文件都在同一个目录中,那么将这个“在Windows中显示这个文件”命令工作会很好 - 至少如果它不可能那么它就不是一个主要功能。

#6


0  

I suppose you can use FindWindowEx to get the SysListView32 of Windows Explorer, then use SendMessage with LVM_SETITEMSTATE to select the items. The difficulty being to know the position of the items... Perhaps LVM_FINDITEM can be used for this.

我想您可以使用FindWindowEx来获取Windows资源管理器的SysListView32,然后使用SendMessage和LVM_SETITEMSTATE来选择项目。难以知道项目的位置......也许LVM_FINDITEM可以用于此。

#7


0  

Grr i would like to do this as well. Media Player does it when you select 2+ files and right click and do "open file location" but not exactly sure how (nor do i really feel like spending the time w/ procmon to figure it out).

Grr我也想这样做。当您选择2个以上的文件时,媒体播放器会执行此操作并右键单击并执行“打开文件位置”但不完全确定如何(我也不想花时间与procmon一起弄明白)。

#1


17  

This should be possible with the shell function SHOpenFolderAndSelectItems

这应该可以使用shell函数SHOpenFolderAndSelectItems

EDIT

Here is some sample code showing how to use the function in C/C++, without error checking:

下面是一些示例代码,展示了如何在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  

The true way of selecting multiple files in Explorer is the next

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

Unmanaged code looks like this (compiled from China code posts with fixing its bugs)

非托管代码看起来像这样(从中国代码帖子编译修复其错误)

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  

it cannot be done through explorer.exe

它无法通过explorer.exe完成

#4


1  

Depending on what you actually want to accomplish you may be able to do it with AutoHotKey. It is an amazing free tool for automating things you normally can't do. It should come with Windows. This script will select your file and highlight the next two files below it when you hit F12.

根据您实际想要实现的目标,您可以使用AutoHotKey进行操作。它是一个惊人的免费工具,可以自动执行您通常无法做的事情。它应该与Windows一起提供。当您点击F12时,此脚本将选择您的文件并突出显示其下面的下两个文件。

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

It is also possible to just put those two middle lines in a text file and then pass it is a parm to autohotkey.exe. They have an option to compile the script also, which would make it a standalone exe that you could call. Works great with a great help file.

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

@Orion, It is possible to use autohotkey from C#. You can make an autohotkey script into a standalone executable (about 400k) that can be launched by your C# app (just the way you are launching explorer). You can also pass it command line parameters. It does not have any runtime requirements.

@Orion,可以使用C#中的autohotkey。您可以将autohotkey脚本创建为可以由C#app启动的独立可执行文件(大约400k)(就像启动资源管理器一样)。您也可以传递命令行参数。它没有任何运行时要求。

#5


1  

This is one of those questions where it may be good to consider what you're trying to achieve, and whether there's a better method.

这是一个问题,其中可能很好地考虑你想要实现的目标,以及是否有更好的方法。

To add some more context - Our company develops a C# client application, which allows users to load files and do stuff with them, kind of like how iTunes manages your MP3 files without showing you the actual file on disk.

添加更多上下文 - 我们公司开发了一个C#客户端应用程序,它允许用户加载文件并使用它们进行操作,有点像iTunes管理MP3文件而不向您显示磁盘上的实际文件。

It's useful to select a file in the application, and do a 'Show me this file in Windows Explorer` command - this is what I'm trying to achieve, and have done so for single files.

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

We have a ListView which allows users to select multiple files within the application, and move/delete/etc them. It would be nice to have this 'show me this file in windows' command work for multiple selected files - at least if all the source files are in the same directory, but if it's not possible then it's not a major feature.

我们有一个ListView,允许用户在应用程序中选择多个文件,并移动/删除/等等。如果所有的源文件都在同一个目录中,至少如果所有的源文件都在同一个目录中,那么将这个“在Windows中显示这个文件”命令工作会很好 - 至少如果它不可能那么它就不是一个主要功能。

#6


0  

I suppose you can use FindWindowEx to get the SysListView32 of Windows Explorer, then use SendMessage with LVM_SETITEMSTATE to select the items. The difficulty being to know the position of the items... Perhaps LVM_FINDITEM can be used for this.

我想您可以使用FindWindowEx来获取Windows资源管理器的SysListView32,然后使用SendMessage和LVM_SETITEMSTATE来选择项目。难以知道项目的位置......也许LVM_FINDITEM可以用于此。

#7


0  

Grr i would like to do this as well. Media Player does it when you select 2+ files and right click and do "open file location" but not exactly sure how (nor do i really feel like spending the time w/ procmon to figure it out).

Grr我也想这样做。当您选择2个以上的文件时,媒体播放器会执行此操作并右键单击并执行“打开文件位置”但不完全确定如何(我也不想花时间与procmon一起弄明白)。