打赏

一、常规方法

给定一个文件路径,打开文件夹并定位到文件,通常所用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);
                }
            }
        }
    }

试用一下:

非常完美。而且如果其目录已打开,它会已打开的目录中选择而不会新开文件夹,更人性化。

posted on 2018-02-03 11:26  楚人无衣  阅读(6357)  评论(1编辑  收藏  举报