一、常規方法
給定一個文件路徑,打開文件夾並定位到文件,通常所用shell命令為:explorer.exe /select,filepath。
c#以進程啟動之為:
if (File.Exists(fileName)) { Process.Start("explorer", "/select,\"" + fileName + "\""); }
此命令對於一般文件名是適用的,是最為簡便的方法。
但項目中碰到特殊文件名,explorer.exe就不認了,它找不到,它默認跳到我的文檔目錄。
比如下列文件名:
它在c#代碼中,unicode字符實為:
而在命令行窗口中,以explorer /select,執行之,則又如下:
結果它自然是找不到的,所以它打開了我的文檔目錄。
二、SHOpenFolderAndSelectItems API
萬能的stackoverflow!
這個純粹技術的網站,從上受益良多。曾在上面扯過淡,立馬被警告,從此收斂正容。
蛛絲螞跡,找到了SHOpenFolderAndSelectItems這個API,解決問題:
/// <summary> /// 打開路徑並定位文件...對於@"h:\Bleacher Report - Hardaway with the safe call ??.mp4"這樣的,explorer.exe /select,d:xxx不認,用API整它 /// </summary> /// <param name="filePath">文件絕對路徑</param> [DllImport("shell32.dll", ExactSpelling = true)] private static extern void ILFree(IntPtr pidlList); [DllImport("shell32.dll", CharSet = CharSet.Unicode, ExactSpelling = true)] private static extern IntPtr ILCreateFromPathW(string pszPath); [DllImport("shell32.dll", ExactSpelling = true)] private static extern int SHOpenFolderAndSelectItems(IntPtr pidlList, uint cild, IntPtr children, uint dwFlags); public static void ExplorerFile(string filePath) { if (!File.Exists(filePath) && !Directory.Exists(filePath)) return; if (Directory.Exists(filePath)) Process.Start(@"explorer.exe", "/select,\"" + filePath + "\""); else { IntPtr pidlList = ILCreateFromPathW(filePath); if (pidlList != IntPtr.Zero) { try { Marshal.ThrowExceptionForHR(SHOpenFolderAndSelectItems(pidlList, 0, IntPtr.Zero, 0)); } finally { ILFree(pidlList); } } } }
試用一下:
非常完美。而且如果其目錄已打開,它會已打開的目錄中選擇而不會新開文件夾,更人性化。