在 Windows 资源管理器中以编程方式选择多个文件
-
08-06-2019 - |
题
我可以在 Windows 资源管理器中显示并选择单个文件,如下所示:
explorer.exe /select, "c:\path\to\file.txt"
但是,我不知道如何选择多个文件。我尝试过的 select 排列都不起作用。
笔记:我查看了这些页面的文档,但都没有帮助。
https://support.microsoft.com/kb/314853
http://www.infocellar.com/Win98/explorer-switches.htm
解决方案
这应该可以通过 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);
其他提示
在资源管理器中选择多个文件的真正方法是下一个
非托管代码看起来像这样(从中国代码帖子编译并修复了错误)
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);
}
}
}
它不能通过explorer.exe来完成
根据您实际想要完成的任务,您可以使用 自动热键. 。它是一个令人惊叹的免费工具,可以自动化您通常无法完成的事情。它应该随 Windows 一起提供。当您按 F12 时,此脚本将选择您的文件并突出显示其下面的两个文件。
F12::
run explorer.exe /select`, "c:\path\to\file.txt"
SendInput {Shift Down}{Down}{Down}{Shift Up}
return
也可以将中间两行放入文本文件中,然后将其作为参数传递给 autohotkey.exe。他们还可以选择编译脚本,这将使其成为您可以调用的独立 exe。配合强大的帮助文件,效果非常好。
@Orion,可以使用 C# 中的自动热键。您可以将 autohotkey 脚本制作成独立的可执行文件(大约 400k),该可执行文件可以由您的 C# 应用程序启动(就像启动资源管理器一样)。您还可以向其传递命令行参数。它没有任何运行时要求。
这是其中一个最好考虑您想要实现的目标以及是否有更好的方法的问题。
要添加更多上下文 - 我们的公司开发了一个C#客户端应用程序,该应用程序允许用户加载文件并与它们一起做事,就像iTunes如何管理您的MP3文件而无需在磁盘上显示实际文件。
在应用程序中选择一个文件,然后执行“在 Windows 资源管理器中显示此文件”命令非常有用 - 这就是我想要实现的目标,并且已经对单个文件执行了此操作。
我们有一个 ListView,它允许用户在应用程序中选择多个文件,并移动/删除等。如果“在 Windows 中显示此文件”命令适用于多个选定的文件,那就太好了 - 至少如果所有源文件都位于同一目录中,但如果不可能,那么它就不是主要功能。
我想你可以使用 FindWindowEx
获取Windows资源管理器的SysListView32,然后使用 SendMessage
和 LVM_SETITEMSTATE
选择项目。困难在于知道物品的位置......也许 LVM_FINDITEM
可以用于此目的。
我也想这样做。当您选择 2 个以上文件并右键单击并执行“打开文件位置”时,媒体播放器会执行此操作,但不完全确定如何执行(我也不想花时间与 procmon 来弄清楚)。