7

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

我正在尝试制作一个控制台程序来自动化一些我无法用 BAT 文件完成的任务。我想从 Windows SDK 调用“signcode.exe”,在我的系统 PATH 中包含所有工具的 bin 文件夹,我可以从任何地方调用“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 文件夹。手动设置也不起作用。

我什至尝试按照 MSDN 页面上的EnvironmentVariables Property所示设置 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,但是如果我从同一提示符运行此应用程序,它不会注册该路径。

4

7 回答 7

16

添加到 mhutch 的答案中:它确实考虑了 PATH,但我注意到您实际上需要重新启动 Visual Studio 以获取任何路径更改。这有点偷偷摸摸。

于 2012-10-04T14:46:25.110 回答
5

我很确定 Process.Start 确实尊重 PATH。

  • 您确定您的 signCommand 值正确吗?
  • PATH 中的目录值是否使用引号指定?文档提到不会尊重这些价值观。

请注意,FileName 也可以是可执行文件的完整路径。

于 2011-11-03T23:48:09.607 回答
3

如果您最近更新了 PATH,请务必重新启动 Visual Studio。环境变量在 Visual Studio 启动时加载。请注意,这适用于调试模式执行。

于 2012-11-07T22:09:34.943 回答
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 路径的路径,除非有某种方法可以在不使用引号的情况下向路径添加带有空格的内容。

于 2011-11-04T00:22:14.853 回答
1

我相信您正在寻找ProcessStartInfo.WorkingDirectory 属性

于 2011-11-03T23:45:55.893 回答
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);
于 2011-11-03T23:47:13.577 回答
0

您的代码似乎确实为我考虑了路径。

很难说你的情况可能有什么问题,但你可以尝试通过以下方式运行你的命令cmd.exe

sign.StartInfo.FileName = "cmd";
sign.StartInfo.Arguments = "/c signtool.exe ...";
于 2011-11-03T23:49:03.057 回答