代码之家  ›  专栏  ›  技术社区  ›  Jürgen Steinblock

检查Windows路径中是否存在可执行文件

  •  56
  • Jürgen Steinblock  · 技术社区  · 14 年前

    如果我用 ShellExecute (或在.NET中 System.Diagnostics.Process.Start() )要启动的文件名进程不需要是完整路径。

    如果我想启动记事本,我可以使用

    Process.Start("notepad.exe");
    

    而不是

    Process.Start(@"c:\windows\system32\notepad.exe");
    

    因为导演 c:\windows\system32 是PATH环境变量的一部分。

    如何在不执行进程和不分析路径变量的情况下检查路径上是否存在文件?

    System.IO.File.Exists("notepad.exe"); // returns false
    (new System.IO.FileInfo("notepad.exe")).Exists; // returns false
    

    但我需要这样的东西:

    System.IO.File.ExistsOnPath("notepad.exe"); // should return true
    

    System.IO.File.GetFullPath("notepad.exe"); // (like unix which cmd) should return
                                               // c:\windows\system32\notepad.exe
    

    BCL中是否有用于执行此任务的预定义类?

    6 回复  |  直到 14 年前
        1
  •  51
  •   Michael Szvetits    8 年前

    System.IO.File.Exists

    public static bool ExistsOnPath(string fileName)
    {
        return GetFullPath(fileName) != null;
    }
    
    public static string GetFullPath(string fileName)
    {
        if (File.Exists(fileName))
            return Path.GetFullPath(fileName);
    
        var values = Environment.GetEnvironmentVariable("PATH");
        foreach (var path in values.Split(';'))
        {
            var fullPath = Path.Combine(path, fileName);
            if (File.Exists(fullPath))
                return fullPath;
        }
        return null;
    }
    
        2
  •  26
  •   Hans Passant    7 年前

     Process.Start("wordpad.exe");
    

        3
  •  14
  •   Jos van Egmond    5 年前

    public static bool ExistsOnPath(string exeName)
    {
        try
        {
            using (Process p = new Process())
            {
                p.StartInfo.UseShellExecute = false;
                p.StartInfo.FileName = "where";
                p.StartInfo.Arguments = exeName;
                p.Start();
                p.WaitForExit();
                return p.ExitCode == 0;
            }
        }
        catch(Win32Exception)
        {
            throw new Exception("'where' command is not on path");
        }
    }
    
    public static string GetFullPath(string exeName)
    {
        try
        {
            using (Process p = new Process())
            {
                p.StartInfo.UseShellExecute = false;
                p.StartInfo.FileName = "where";
                p.StartInfo.Arguments = exeName;
                p.StartInfo.RedirectStandardOutput = true;
                p.Start();
                string output = p.StandardOutput.ReadToEnd();
                p.WaitForExit();
    
                if (p.ExitCode != 0)
                    return null;
    
                // just return first match
                return output.Substring(0, output.IndexOf(Environment.NewLine));
            }
        }
        catch(Win32Exception)
        {
            throw new Exception("'where' command is not on path");
        }
    }
    
        4
  •  6
  •   Eugene Mala    6 年前
        5
  •  5
  •   Ron    6 年前

    /// <summary>
    /// Gets the full path of the given executable filename as if the user had entered this
    /// executable in a shell. So, for example, the Windows PATH environment variable will
    /// be examined. If the filename can't be found by Windows, null is returned.</summary>
    /// <param name="exeName"></param>
    /// <returns>The full path if successful, or null otherwise.</returns>
    public static string GetFullPathFromWindows(string exeName)
    {
        if (exeName.Length >= MAX_PATH)
            throw new ArgumentException($"The executable name '{exeName}' must have less than {MAX_PATH} characters.",
                nameof(exeName));
    
        StringBuilder sb = new StringBuilder(exeName, MAX_PATH);
        return PathFindOnPath(sb, null) ? sb.ToString() : null;
    }
    
    // https://docs.microsoft.com/en-us/windows/desktop/api/shlwapi/nf-shlwapi-pathfindonpathw
    // https://www.pinvoke.net/default.aspx/shlwapi.PathFindOnPath
    [DllImport("shlwapi.dll", CharSet = CharSet.Unicode, SetLastError = false)]
    static extern bool PathFindOnPath([In, Out] StringBuilder pszFile, [In] string[] ppszOtherDirs);
    
    // from MAPIWIN.h :
    private const int MAX_PATH = 260;
    
        6
  •  2
  •   alleey    13 年前