Может ли Process.Start () учитывать систему PATH?

Я искал и экспериментировал какое-то время с этим, но мне не повезло.

Я пытаюсь создать консольную программу для автоматизации некоторых задач, которые я не мог сделать с файлом BAT. Я хочу вызвать «signcode.exe» из Windows SDK, папку bin со всеми инструментами в моей системе PATH, и я могу вызвать «signcode» из любого места, но Process.Start игнорирует этот путь.

Текущий код:

 System.Diagnostics.Process sign = new System.Diagnostics.Process(); sign.StartInfo.FileName = signCommand.Substring(0, signCommand.IndexOf(' ')); // signtool.exe sign.StartInfo.Arguments = signCommand.Substring(signCommand.IndexOf(' ') + 1); // /sign /a file1 file2 // sign.StartInfo.EnvironmentVariables["Path"] = Environment.GetEnvironmentVariable("PATH"); // This doesn't work either sign.StartInfo.UseShellExecute = false; sign.StartInfo.RedirectStandardOutput = true; sign.StartInfo.RedirectStandardError = true; sign.Start(); // Throws Win32Exception - The system cannot find the file specified 

Я подтвердил, что StartInfo.EnvironmentVariables [“Путь”] соответствует моему системному пути и содержит папку Windows SDK. Настройка вручную также не работает.

Я даже попытался установить TempPath, как показано на странице MSDN для свойства EnvironmentVariables , но это тоже не сработало. Интересно, почему вы могли бы установить это, если это не повлияет.

Если System.Diagnostics.Process не может использовать путь, есть ли какие-либо другие функции, которые я мог бы использовать? Я также хотел бы видеть вывод команды в моем консольном приложении.

Вот некоторые дополнительные значения отладки:

 Console.WriteLine("Sign Filename = '{0}'", sign.StartInfo.FileName); Sign Filename = 'signtool.exe' Console.WriteLine("Sign Arguments = '{0}'", sign.StartInfo.Arguments); Sign Arguments = '/sign /f C:\Visual Studio\Projects\MGInsight\MGInsight\APPARENTINC.pfx /t http://timestamp.comodoca.com/authenticode "C:\Visual Studio\Projects\MGInsight\MGInsight\Publish\Application Files\\MGInsight_0_9_1_85\MGInsight.exe" "C:\Visual Studio\Projects\MGInsight\MGInsight\Publish\Application Files\\MGInsight_0_9_1_85\XPXScanner.dll" "C:\Visual Studio\Projects\MGInsight\MGInsight\Publish\Application Files\\MGInsight_0_9_1_85\NetworkCalculations.dll"' Console.WriteLine("Sign Path = '{0}'", sign.StartInfo.EnvironmentVariables["Path"]); Sign Path = 'C:\Windows\system32;C:\Windows;C:\Windows\System32\Wbem;C:\Windows\System32\WindowsPowerShell\v1.0\;"C:\Program Files\Intel\WiFi\bin\";"C:\Program Files\Common Files\Intel\WirelessCommon\";"C:\Program Files (x86)\cwRsync\bin";"C:\Program Files (x86)\Git\cmd";"C:\Program Files (x86)\Git\bin";"C:\Program Files (x86)\Zend\ZendServer\bin";"C:\Program Files (x86)\Zend\ZendServer\share\ZendFramework\bin";"C:\Program Files\Java\jre6\bin";"C:\Program Files (x86)\Microsoft Visual Studio 10.0\Common7\IDE\";"C:\Program Files\Microsoft Windows Performance Toolkit\";C:\MinGW\bin;"C:\Program Files (x86)\Microsoft\ILMerge";"C:\Program Files (x86)\Microsoft SDKs\Windows\v7.0A\Bin";C:\Program Files (x86)\Nmap' 

Путь "C:\Program Files (x86)\Microsoft SDKs\Windows\v7.0A\Bin" – это где signtool.exe есть, и я могу запустить его из командной строки, просто набрав signtool , но если я запустил это приложение из того же приглашения он не регистрирует этот путь.

Я уверен, что Process.Start уважает PATH.

  • Вы уверены, что ваше значение signCommand верное?
  • Указывается ли значение каталога в PATH с использованием кавычек? В документах упоминается, что такие значения не будут соблюдаться.

Обратите внимание, что FileName также может быть полным путем к исполняемому файлу.

Добавляя к ответу mhutch: он действительно учитывает PATH, но я заметил, что вам действительно нужно перезапустить Visual Studio, чтобы выбрать любые изменения пути. Это вроде подлый.

Ну, я думаю, проблема была связана с тем, что сказал mhutch, из документов MSDN:

 If you have a path variable declared in your system using quotes, you must fully qualify that path when starting any process found in that location. Otherwise, the system will not find the path. For example, if c:\mypath is not in your path, and you add it using quotation marks: path = %path%;"c:\mypath", you must fully qualify any process in c:\mypath when starting it. 

Сначала я это видел, но это казалось странным, поэтому я не обращал на это внимания. Не знаю, почему это так, но похоже.

Я попытался скопировать файл signtool.exe в C: \ sign \ tool \ bin и добавил его к моему пути, а затем мой код работал, поэтому я думаю, потому что у меня есть кавычки в этом пути из-за пробелов, я SOL и мне придется вручную найдите путь для пути к SDK Windows, если не существует способа добавить что-либо с пробелами в путь без использования кавычек.

Если вы недавно обновили PATH, обязательно перезапустите Visual Studio. Переменные среды загружаются при запуске Visual Studio. Обратите внимание, что это относится к выполнению режима DEBUG.

Я считаю, что вы ищете свойство ProcessStartInfo.WorkingDirectory .

Имя файла StartInfo – это фактически полный путь к исполняемому файлу

Например, на обертке у меня для x264, она выглядит так:

 x264Start.FileName = Directory.GetCurrentDirectory() + @"\Tools\x264\x264x86-r1995.exe"; 

Я бы проверил код, добавив туда try {}, catch {} и записав фактическое имя файла, которое вы пытаетесь вызвать в отладку, если у вас есть ошибка.

В противном случае добавьте что-то вроде ниже:

  if (File.exists(sign.FileName)) { sign.Start(); } else { Console.WriteLine("Can't find {0}", sign.FileName); throw new Exception("File doesn't exist"); } 

EDIT: добавлен полный пример – он ищет CCleaner, а затем запускает его с помощью переключателя «/ AUTO». Просто проверено и отлично работает.

  // detect if 64-bit system string programFiles = ""; if (Environment.GetEnvironmentVariable("PROCESSOR_ARCHITECTURE").Contains("64")) { Console.WriteLine("#info# x64 detected"); programFiles = Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles); } else { Console.WriteLine("#info# x86 detected"); programFiles = Environment.GetFolderPath(Environment.SpecialFolder.ProgramFilesX86); } // search string[] dirs = Directory.GetDirectories(programFiles, "CCleaner", SearchOption.AllDirectories); string[] exes = Directory.GetFiles(programFiles, "CCleaner64.exe", SearchOption.AllDirectories); //debug only foreach (string s in dirs) { Console.WriteLine(s); } foreach (string s in exes) { Console.WriteLine(s); } // access directly ProcessStartInfo CCleaner = new ProcessStartInfo(exes[0], "/AUTO"); Process.Start(CCleaner); 

Ваш код, кажется, учитывает меня.

Трудно сказать, что может быть неправильным в вашем случае, но вы можете попробовать запустить команду через cmd.exe :

 sign.StartInfo.FileName = "cmd"; sign.StartInfo.Arguments = "/c signtool.exe ...";