我想编写一个函数,你可以通过传递一个文件路径来使用它,例如:
C:\FOLDER\SUBFOLDER\FILE.TXT
我希望打开Windows资源管理器并定位到包含该文件的文件夹,然后在该文件夹中选择该文件(类似于许多程序中使用的“在文件夹中显示”概念)。
我应该如何做?
不使用Win32 shell函数的最简单方法是使用/select
参数启动explorer.exe。例如,启动进程
explorer.exe /select,"C:\Folder\subfolder\file.txt"
将打开一个新的资源管理器窗口到C:\Folder\subfolder,并选择file.txt文件。
如果您希望以编程方式而不启动新进程执行此操作,则需要使用shell函数SHOpenFolderAndSelectItems
,这是explorer.exe内部使用的/select
命令。请注意,这需要使用PIDL,并且如果您不熟悉shell API的工作原理,则可能会很麻烦。
以下是基于/select
方法的完整程序化实现,其中路径清理感谢@Bhushan和@tehDorf的建议:
public bool ExploreFile(string filePath) {
if (!System.IO.File.Exists(filePath)) {
return false;
}
//Clean up file path so it can be navigated OK
filePath = System.IO.Path.GetFullPath(filePath);
System.Diagnostics.Process.Start("explorer.exe", string.Format("/select,\"{0}\"", filePath));
return true;
}
参考资料: Explorer.exe 命令行开关
SHOpenFolderAndSelectItems
肯定更有效率和节约资源。 - Mahmoud Al-QudsifilePath = System.IO.Path.GetFullPath(filePath);
来清理文件路径,而不是使用 Regex
。它将规范化目录分隔符,并解析相对路径,例如如果您传递类似于 @"..\some\relative\file\path.txt"
或 @"C:\Some\relative\..\file\path.txt"
的内容。您还可以更新示例以使用新的字符串插值:Process.Start("explorer.exe", $"/select,\"{filePath}\"");
。 - tehDorfSHOpenFolderAndSelectItems
慢,并且往往会在后台打开资源管理器。因此,我推荐使用SHOpenFolderAndSelectItems
。 - undefinedvoid OpenFolderAndSelectItem(String filename)
{
// Parse the full filename into a pidl
PIDLIST_ABSOLUTE pidl;
SFGAO flags;
SHParseDisplayName(filename, null, out pidl, 0, out flags);
try
{
// Open Explorer and select the thing
SHOpenFolderAndSelectItems(pidl, 0, null, 0);
}
finally
{
// Use the task allocator to free to returned pidl
CoTaskMemFree(pidl);
}
}
为了跟进@Mahmoud Al-Qudsi的回答。当他说“启动进程”时,这是对我有用的方法:
// assume variable "path" has the full path to the file, but possibly with / delimiters
for ( int i = 0 ; path[ i ] != 0 ; i++ )
{
if ( path[ i ] == '/' )
{
path[ i ] = '\\';
}
}
std::string s = "explorer.exe /select,\"";
s += path;
s += "\"";
PROCESS_INFORMATION processInformation;
STARTUPINFOA startupInfo;
ZeroMemory( &startupInfo, sizeof(startupInfo) );
startupInfo.cb = sizeof( STARTUPINFOA );
ZeroMemory( &processInformation, sizeof( processInformation ) );
CreateProcessA( NULL, (LPSTR)s.c_str(), NULL, NULL, FALSE, 0, NULL, NULL, &startupInfo, &processInformation );