给定命令(如bin/server.exe
或ping
)的命令行样式路径,我如何获得该可执行文件的完整路径(如cmd或Process.Start
将解析它)?
我尝试了Path.GetFullPath
,但它总是相对于工作目录展开。它正确地扩展了bin/server.exe
,但是给定ping
,它返回c:usersmattping
(不存在)。我想要c:Windowssystem32ping.exe
。
编辑:我想要与cmd相同的行为。一些注意事项:
- 当路径中有一个本地可执行文件与该文件同名时,cmd首选本地可执行程序
- cmd可以将命令
server
扩展为server.bat
或server.exe
(添加文件扩展名)
我还尝试了Windows的命令行工具where
。它做几乎我想要:
显示与搜索模式匹配的文件的位置。默认情况下,搜索是沿着当前目录和PATH环境变量指定的路径进行的。
>where ping
C:WindowsSystem32PING.EXE
>where binserver
INFO: Could not find files for the given pattern(s).
(这个问题很难找到,因为"路径"这个词有两个不同的含义)
考虑到PATHEXT,从Serj Tm的回答中窃取(对不起!对他+1):
public static string WhereSearch(string filename)
{
var paths = new[]{ Environment.CurrentDirectory }
.Concat(Environment.GetEnvironmentVariable("PATH").Split(';'));
var extensions = new[]{ String.Empty }
.Concat(Environment.GetEnvironmentVariable("PATHEXT").Split(';')
.Where(e => e.StartsWith(".")));
var combinations = paths.SelectMany(x => extensions,
(path, extension) => Path.Combine(path, filename + extension));
return combinations.FirstOrDefault(File.Exists);
}
对不起,缩进有点满了——我试图让它不滚动。我不知道StartsWith检查是否真的有必要——我不确定CMD如何处理没有前导点的pathext条目。
public static string GetFullPath(string filename)
{
return new[]{Environment.CurrentDirectory}
.Concat(Environment.GetEnvironmentVariable("PATH").Split(';'))
.Select(dir => Path.Combine(dir, filename))
.FirstOrDefault(path => File.Exists(path));
}
如果您只对搜索当前目录和PATH环境变量中指定的路径感兴趣,可以使用以下代码段:
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;
}
您必须搜索整个磁盘。
Windows可以响应iexplore、ping、cmd等,因为它们在注册表项下:
HKEY_LOCAL_MACHINE
SOFTWARE
Microsoft
Windows
CurrentVersion
App Paths
唯一的其他方法是在整个磁盘上搜索应用程序。
编辑:我的理解是,你想搜索任何随机的可执行文件名,而不是Windows已知的名称。。
internal class Program
{
static void Main(string[] args)
{
string fullPath = GetExactPathFromEnvironmentVar("ping.exe");
if (!string.IsNullOrWhiteSpace(fullPath))
Console.WriteLine(fullPath);
else
Console.WriteLine("Not found");
}
static string GetExactPathFromEnvironmentVar(string program)
{
var pathVar = System.Environment.GetEnvironmentVariable("PATH");
string[] folders = pathVar.Split(';');
foreach (var folder in folders)
{
string path = Path.Combine(folder, program);
if (File.Exists(path))
{
return path;
}
}
return null;
}
}
HTH