如果我使用ShellExecute(或在.net中System.Diagnostics.Process.Start())运行进程,则启动文件名进程不需要是完整路径.
如果我想开始记事本,我可以使用
Process.Start("notepad.exe");
Run Code Online (Sandbox Code Playgroud)
代替
Process.Start(@"c:\windows\system32\notepad.exe");
Run Code Online (Sandbox Code Playgroud)
因为direcotry c:\windows\system32是PATH环境变量的一部分.
如何在不执行进程且不解析PATH变量的情况下检查PATH上是否存在文件?
System.IO.File.Exists("notepad.exe"); // returns false
(new System.IO.FileInfo("notepad.exe")).Exists; // returns false
Run Code Online (Sandbox Code Playgroud)
但我需要这样的东西:
System.IO.File.ExistsOnPath("notepad.exe"); // should return true
Run Code Online (Sandbox Code Playgroud)
和
System.IO.File.GetFullPath("notepad.exe"); // (like unix which cmd) should return
// c:\windows\system32\notepad.exe
Run Code Online (Sandbox Code Playgroud)
是否有预定义的类可以在BCL中执行此任务?
dig*_*All 57
我认为没有任何内置功能,但您可以使用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(Path.PathSeparator))
{
var fullPath = Path.Combine(path, fileName);
if (File.Exists(fullPath))
return fullPath;
}
return null;
}
Run Code Online (Sandbox Code Playgroud)
Han*_*ant 27
这是有风险的,除了在PATH中搜索目录之外还有很多其他内容.试试这个:
Process.Start("wordpad.exe");
Run Code Online (Sandbox Code Playgroud)
可执行文件存储在我的机器上的c:\ Program Files\Windows NT\Accessories中,该目录不在路径上.
HKCR\Applications和HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\App Paths键也在查找可执行文件中发挥作用.我相当确定有这样的地雷,64位版本的Windows中的目录虚拟化可能会让你失望.
为了使这更可靠,我认为你需要pinvoke AssocQueryString().不确定,从来没有必要.更好的方法当然不必提问.
Dun*_*unc 16
好吧,我认为更好的方式......
这使用where命令,该命令至少在Windows 7/Server 2003上可用:
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");
}
}
Run Code Online (Sandbox Code Playgroud)
我尝试了Dunc的"where"过程并且它有效,但它很慢且资源很重,并且存在孤立进程的轻微危险.
我喜欢Eugene Mala关于PathFindOnPath的提示,因此我将其作为一个完整的答案充实.这就是我用于自定义内部工具的内容.
/// <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;
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
27607 次 |
| 最近记录: |