检查Windowspath中是否存在可执行文件

如果我使用ShellExecute (或使用System.Diagnostics.Process.Start()在.net中)运行进程,则启动的文件名进程不需要是完整path。

如果我想开始记事本,我可以使用

 Process.Start("notepad.exe"); 

代替

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

因为direcotry c:\windows\system32是PATH环境variables的一部分。

我怎样才能检查PATH上是否存在一个文件,而不执行进程和parsingPATHvariables?

 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中的这个任务?

我认为没有什么内置的,但你可以用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; } 

这是有风险的,除了在PATH中search目录之外,还有很多。 尝试这个:

  Process.Start("wordpad.exe"); 

可执行文件存储在我的机器上的c:\ Program Files \ Windows NT \ Accessories目录不在path上。

HKCR \ Applications和HKLM \ SOFTWARE \ Microsoft \ Windows \ CurrentVersion \ App Paths键也在查找可执行文件中发挥作用。 我相当肯定有这样的附加地雷,64位版本的Windows中的目录虚拟化可能会让你失望。

为了使这更可靠,我认为你需要pinvoke AssocQueryString()。 不知道,从来没有这个需要。 更好的方法当然不必问这个问题。

好的,我觉得更好的方法

这使用至less在Windows 7 / Server 2003上可用的where命令:

 public static bool ExistsOnPath(string exeName) { try { 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 { 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"); } } 

我是在同样的事情,我认为我现在最好的select是使用本地调用CreateProcess创build一个进程暂停和注意成功; 立即终止该过程。 终止暂停的过程不应该导致任何资源stream血[引文需要:)]

我可能无法弄清楚实际使用的path,但是对于ExistsOnPath()这个简单的需求应该这样做,直到有更好的解决scheme。