我一直在寻找和尝试一段时间,但我没有运气。
我正在尝试制作一个控制台程序来自动完成一些我无法用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文件夹。手动设置也不起作用。
我甚至尝试设置EnvironmentVariables Property的MSDN页面上显示的TempPath,但这也不起作用。我想知道为什么如果没有效果你就能设置它。
如果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
从命令提示符运行它,但如果我从同一个提示符运行此应用程序,它不会注册该路径。
答案 0 :(得分:14)
添加到mhutch的答案:确实需要考虑PATH,但我注意到你实际上需要重新启动Visual Studio以获取任何路径更改。这有点偷偷摸摸。
答案 1 :(得分:5)
我很确定Process.Start确实尊重PATH。
请注意,FileName也可以是可执行文件的完整路径。
答案 2 :(得分:2)
好吧,我猜这个问题与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路径的路径,除非有一些方法可以在不使用引号的情况下向路径添加空格。
答案 3 :(得分:2)
如果您最近更新了PATH,请务必重新启动Visual Studio。环境变量在Visual Studio启动时加载。请注意,这适用于DEBUG模式执行。
答案 4 :(得分:1)
答案 5 :(得分:1)
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);
答案 6 :(得分:0)
您的代码似乎确实考虑了我的路径。
很难说出你的情况可能出现什么问题,但你可以尝试通过cmd.exe
运行命令:
sign.StartInfo.FileName = "cmd";
sign.StartInfo.Arguments = "/c signtool.exe ...";