如何使用环境路径找到可能不完全限定的文件?

问题描述 投票:0回答:6

我有一个可执行文件名称,例如“cmd.exe”,需要解析它的完全限定路径。我知道该 exe 出现在 PATH 环境变量中列出的目录之一中。有没有办法在不解析和测试 PATH 变量中的每个目录的情况下解析完整路径?基本上我不想这样做:

foreach (string entry in Environment.GetEnvironmentVariable("PATH").Split(';'))
    ...

一定有更好的方法,对吧?

c# .net environment-variables relative-path path
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));

也许更具可读性?


2
投票

这似乎是一个很好的方法——据我所知,在

PATH
环境变量中搜索目录是 Windows 在尝试解析路径时所做的事情。


2
投票

嗯,我确实找到了以下内容;但是,我想我会坚持托管实施。

    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;
        }
    }

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"

0
投票

在此处添加到现有答案的几条注释,特别是关于制定更加与平台无关的方法:

  • System.IO.Path.PathSeparator
    分割。这在 Windows 上解析为
    ';'
    ,在几乎其他任何东西上解析为
    ':'
    • 还建议通过
      StringSplitOptions.RemoveEmptyEntries
      ,以避免潜在的边缘情况。
  • 检查带或不带扩展名的可执行文件
    .exe
  • 不幸的是,如果您必须处理跨平台支持,事情总是会变得混乱(可读性较差)。对不起。
© www.soinside.com 2019 - 2024. All rights reserved.