C#以管理员身份启动子进程(在CMD窗口中),具有自定义环境变量

时间:2018-04-30 21:00:31

标签: c# winapi cmd

我有一个程序包含一些Windows SDK可执行文件,并在单独的CMD窗口中打开它们。

Process process = new Process();
process.StartInfo.FileName = "cmd.exe";
process.StartInfo.Arguments = "/C signtool.exe [args] & pause";
process.StartInfo.Verb = "runas";
process.Start();

现在,我已将Windows SDK文件夹添加到系统的Path环境变量中。有没有办法以编程方式将Windows SDK文件夹添加到用户的Path环境变量中,或者在将SDK文件夹添加到该特定CMD窗口的Path变量的情况下运行该过程?

这是我需要添加到每个CMD窗口的Path变量的文件夹:

C:\Program Files (x86)\Windows Kits\10\bin\10.0.16299.0\x86

此子流程必须以管理员身份运行。它不需要接收子进程的输出。

2 个答案:

答案 0 :(得分:3)

使用ProcessStartInfo及其Environment属性实例进行设置。

var startInfo = new ProcessStartInfo();
var defaultPath = startInfo.Environment["PATH"];
var newPath = "C:\\Program Files (x86)\\Windows Kits\\10\\bin\\10.0.16299.0\\x86" + ";" + defaultPath;
startInfo.FileName = "cmd.exe";
startInfo.Arguments = "/c set > D:\\env.txt";
startInfo.Verb = "runas";
startInfo.Environment["PATH"] = newPath;
startInfo.UseShellExecute = false; // required to use Environment variables
Process.Start(startInfo);

答案 1 :(得分:0)

这里需要克服许多障碍。

  1. 正如您所发现的,EnvironmentEnvironmentVariables时,ProcessStartInfo的{​​{1}}和UseShellExecute属性无法使用(抛出异常) )。但true仅在VerbUseShellExecute时才会有效(false会被忽略)。这归结为CreateProcess(核心Win32函数)和ShellExecute / ShellExecuteEx(shell函数)之间的差异。
  2. 正如另一位评论者建议的那样,您可以尝试在父进程中设置环境,然后启动子进程。但是,elevated processes don't inherit the environment from a non-elevated parent process
  3. 我愿意打赌,有一种方法可以使用正确的Win32系列调用来获取所需内容,然后调用类似CreateProcessAsUser的内容。我也愿意打赌它会因为必要的struct marshaling而在C#中容易出错并且很难看。因此,我不会试图为您解决这个问题,而是提出另一个建议:

    只需以编程方式编写一个设置环境并调用Verb的批处理脚本。然后,您可以使用当前正在执行的signtool.exe动词来调用该批处理脚本。