如何通过使用环境路径来查找可能没有完全限定的文件?

10
我有一个可执行文件的名称,比如cmd.exe,需要解析它的完全限定路径。我知道该可执行文件出现在PATH环境变量列出的一个目录中。有没有一种方法可以在不解析和测试PATH变量中的每个目录的情况下解析完整路径?基本上,我不想这样做:
foreach (string entry in Environment.GetEnvironmentVariable("PATH").Split(';'))
    ...

肯定有更好的方法,对吧?
6个回答

14

这里是另一种方法:

string exe = "cmd.exe";
string result = Environment.GetEnvironmentVariable("PATH")
    .Split(';')
    .Where(s => File.Exists(Path.Combine(s, exe)))
    .FirstOrDefault();

结果:C:\WINDOWS\system32

使用Path.Combine()方法来处理没有以斜杠结尾的路径。这将正确地连接字符串,以供File.Exists()方法使用。


5

您可以使用Linq进行连接

string path = Environment
                .GetEnvironmentVariable("PATH")
                .Split(';')
                .FirstOrDefault(p => File.Exists(p + filename));

也许更易读一些?

3
我相信在调用File.Exists之前,您需要正确构建路径。 Path.Combine(p, filename) - Lee Jensen
我可以确认这对我没有起作用。 - Rob Baily
如果你关心跨平台性,你还应该将 ';' 替换为 System.IO.Path.PathSeparator';' 适用于 Windows NT 的路径,而其他地区使用 ':' - undefined

3

我找到了以下内容;不过,我想我还是会坚持使用托管实现。

    static class Win32
    {
        [DllImport("shlwapi.dll", CharSet = CharSet.Auto, SetLastError = false)]
        static extern bool PathFindOnPath([MarshalAs(UnmanagedType.LPTStr)] StringBuilder pszFile, IntPtr unused);

        public static bool FindInPath(String pszFile, out String fullPath)
        {
            const int MAX_PATH = 260;
            StringBuilder sb = new StringBuilder(pszFile, MAX_PATH);
            bool found = PathFindOnPath(sb, IntPtr.Zero);
            fullPath = found ? sb.ToString() : null;
            return found;
        }
    }

2

这似乎已经是一个相当不错的方式 - 据我所知,当 Windows 尝试解析路径时,搜索 PATH 环境变量中的目录就是它的做法。


0
几点补充说明,特别是关于采用更平台无关的方法:
- 使用 `System.IO.Path.PathSeparator` 进行分割。在 Windows 上,它解析为 `';'`,在其他大多数平台上解析为 `':'`。 - 还建议传递 `StringSplitOptions.RemoveEmptyEntries`,以避免潜在的边缘情况。 - 检查带有和不带有扩展名 `.exe` 的可执行文件。 - 不幸的是,如果你必须处理跨平台支持,事情往往会变得混乱(不易读)。抱歉。

0
我最终写了这个函数:
private static string GetExecutablePath(string executableFileName)
{
    var path = Environment
        .GetEnvironmentVariable("PATH")!
        .Split(';')
        .Select(s => Path.Combine(s, executableFileName))
        .FirstOrDefault(x => File.Exists(x));
    if (path == null)
    {
        throw new Exception($"Cannot find {executableFileName}. Is it installed on your computer?");
    }
    return path;
}

在我的情况下,我想找到 python.exe 的路径,因此我这样调用函数:
GetExecutablePath("python.exe")

在我的情况下,它返回:
"C:\\Program Files\\Python39\\python.exe"

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接