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

Converting C# Application that runs CMD commands to one that runs Powershell commands with administrative 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。我将如何更改此功能以适应新代码。这仍然是最有效的方法吗???

只需更改行:

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

收件人:

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

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

提供了一个有效的解决方案,但有几点值得解释:

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

    的非标准 Windows 安装的问题
    • 此外,鉴于 您通过 .FileName 指定了 完整路径 .WorkingDirectory 属性 是有效地 忽略 并将 .Verb 设置为 runas,因为 .WorkingDirectory 实际上并没有 设置工作目录,但指定在哪里可以找到可执行文件,如果指定仅按名称 - 然而,在%PATH%中查找/ $env:PATH 仍在执行。
  • 虽然将命令传递给 shell 调用的 /c 参数恰好也适用于 PowerShell 的 CLIPowerShell 通常使用 sigil - 作为参数名称的前缀;因此,
    -c-Command 的缩写)是更好的选择。

    • 此外,假定 PowerShell 默认加载其 $PROFILE 初始化文件 (即使使用 -Command-File 调用时,即使这通常是不可取的),最好使用 -NoProfile -Command ...
  • 一般 - 如果您不需要需要海拔 (运行 作为 admin) - 作为通过 子进程 缓慢创建的替代方案=13=], 考虑使用 PowerShell SDK (API), which enables faster in-process execution while also enabling more fine-grained capturing of output streams (which you don't seem to be interested in in your particular scenario; while System.Diagnostics.ProcessStartInfo allows you to capture stdout and stderr output via the .RedirectStandardOutput and .RedirectStandardError properties, note that PowerShell has additional output streams).

基于以上,我建议执行以下操作:

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();

或者,更简洁:

using System;
using System.Diagnostics;

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