将运行CMD命令的C#应用​​程序转换为具有管理特权的运行Powershell命令的应用程序

时间:2019-02-20 18:21:33

标签: c# powershell cmd elevated-privileges

我有一个Visual Studio应用程序,它使用以下功能来运行一系列Cmd命令

public static void AdminEx(string command) //Runs an Administrative Windows Command
    {
        var proc = new System.Diagnostics.ProcessStartInfo();
        proc.UseShellExecute = true;
        proc.WorkingDirectory = @"C:\Windows\System32";
        proc.FileName = @"C:\Windows\System32\cmd.exe";
        proc.Verb = "runas";
        proc.Arguments = "/c " + command;
        proc.WindowStyle = System.Diagnostics.ProcessWindowStyle.Hidden;
        var p = System.Diagnostics.Process.Start(proc);
        p.WaitForExit();
    }

我们最近更新了代码,并转换为Powershell。我将如何更改此功能以适应新代码。这仍然是最有效的方法吗?

2 个答案:

答案 0 :(得分:2)

只需更改行:

proc.FileName = @"C:\Windows\System32\cmd.exe";

收件人:

proc.FileName = @"C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe";

这将使您的软件打开powershell.exe而不是cmd.exe,我无法确定这是否是解决此问题的最佳方法,但我在这里尝试了,并且对我有效。

答案 1 :(得分:0)

Otávio Caldonazo's helpful answer提供了有效的解决方案,但值得解释以下几点:

  • 除非存在安全隐患(有人将非标准的恶意cmd.exe / powershell.exe可执行文件放置在%PATH% / $env:PATH环境变量中列出的文件夹中优先使用标准可执行文件),单独使用可执行文件文件名(即仅cmd.exe / powershell.exe 会更简单-这也避免了根为 not C:\Windows的非标准Windows安装出现问题。

    • 此外,假设您通过.FileName指定了完整路径,则.WorkingDirectory属性实际上会被{em> 忽略,{ {1}}设置为.Verb ,因为runas实际上并不 设置工作目录,而是指定在哪里找到可执行文件< / em>,如果仅按名称指定 -但是,仍会在.WorkingDirectory / %PATH%中进行查找。
  • 虽然$env:PATH参数将命令传递给所调用的外壳程序也恰好与PowerShell的 CLI 一起使用,但 PowerShell通常也使用sigil /c前缀参数名称;因此,
    --c的缩写)是更好的选择。

    • 此外,假设PowerShell会默认加载其-Command初始化文件 (即使使用$PROFILE-Command进行调用,即使通常不希望这样做) ,最好改用-File
  • 通常-如果您不需要需要海拔(以 admin 身份运行) >)-作为通过-NoProfile -Command ...缓慢创建子进程的替代方法,请考虑使用PowerShell SDK (API) ,这样可以更快地实现 执行中执行,同时还可以更细粒度地捕获输出流 (您似乎对此并不感兴趣)在您的特定情况下;虽然powershell.exe允许您通过System.Diagnostics.ProcessStartInfo.RedirectStandardOutput属性捕获stdout和stderr输出,但请注意PowerShell具有additional output streams)。

基于上述内容,我建议您执行以下操作:

.RedirectStandardError

或更简洁地说:

var proc = new System.Diagnostics.ProcessStartInfo();
proc.UseShellExecute = true;
proc.Verb = "runas";
proc.FileName = @"powershell.exe";
proc.Arguments = "-NoProfile -Command " + command;
proc.WindowStyle = System.Diagnostics.ProcessWindowStyle.Hidden;
var p = System.Diagnostics.Process.Start(proc);
p.WaitForExit();