Получить путь к исполняемому из команды (как это делает cmd)
Учитывая путь стиля командной строки к команде, такой как bin/server.exe
или ping
, как я могу получить полный путь к этому исполняемому файлу (так как cmd или Process.Start
разрешат его)?
Я пробовал Path.GetFullPath
, но он всегда расширяется относительно рабочего каталога. Он правильно расшифровывает bin/server.exe
, но, учитывая ping
, он возвращает c:\users\matt\ping
(несуществующий). Я хочу c:\Windows\system32\ping.exe
.
Изменить: Мне хотелось бы, чтобы это было так же, как cmd. Некоторые соображения:
- Когда есть локальный исполняемый файл с тем же именем, что и один в пути, cmd предпочитает локальный
- cmd может расширить команду
server
до server.bat
или server.exe
(добавление расширения файла)
Я также попробовал инструмент командной строки Windows под названием where
. Мне это почти нравится:
Отображает расположение файлов, соответствующих шаблону поиска. По умолчанию поиск выполняется по текущему каталогу и по путям, указанным переменной среды PATH.
>where ping
C:\Windows\System32\PING.EXE
>where bin\server
INFO: Could not find files for the given pattern(s).
(Этот вопрос трудно найти вокруг из-за двух разных значений слова "путь" )
Ответы
Ответ 1
С учетом 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 без ведущей точки.
Ответ 2
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));
}
Ответ 3
Если вас интересует только текущий каталог и пути, указанные в переменной среды 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;
}
Ответ 4
Вам нужно выполнить поиск по всему диску.
Windows может реагировать на такие вещи, как iexplore, ping, cmd и т.д., потому что они находятся в реестре под этим ключом:
HKEY_LOCAL_MACHINE
SOFTWARE
Microsoft
Windows
CurrentVersion
App Paths
Другим способом является поиск всего диска для приложения.
EDIT: Я понял, что вы хотите найти произвольное исполняемое имя, а не те, которые уже известны Windows.
Ответ 5
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;
}
}
НТН