Process.Start()可以考虑系统PATH吗?

我一直在寻找和试验一段时间,但我没有运气。

我正在尝试制作一个控制台程序来自动完成一些我无法用BAT文件完成的任务。 我想从Windows SDK调用“signcode.exe”,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 [“Path”]与我的系统路径匹配,并包含Windows SDK文件夹。 手动设置也不起作用。

我甚至尝试过设置TempPath,如环境变量属性的MSDN页面所示,但这也不起作用。 我想知道为什么你可以设置它,如果它没有效果。

如果System.Diagnostics.Process无法使用该路径,是否还有其他可以使用的function? 我想在我的控制台应用程序中看到命令的输出。

以下是一些额外的调试值:

 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,必须手动搜索Windows SDK路径的路径,除非有某种方法可以在不使用引号的情况下向路径添加空格。

如果最近更新了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"); } 

编辑:添加了一个完整的示例 – 这将搜索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 ...";