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

问题描述 投票:1回答:2

我有一个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。我将如何更改此功能以适应新代码。这仍然是最有效的方式吗?

c# powershell cmd elevated-privileges
2个回答
0
投票

Otávio Caldonazo's helpful answer提供了一个有效的解决方案,但值得解释一些事情:

  • 除非存在安全问题(某人在cmd.exe / powershell.exe环境变量中列出的文件夹中列出了标准可执行文件的非标准恶意%PATH% / $env:PATH可执行文件),否则单独使用可执行文件名更简单,即cmd.exe / powershell.exe - 这也避免了根目录不是C:\Windows的非标准Windows安装的问题。 此外,鉴于您通过.FileName指定了完整路径,.WorkingDirectory属性实际上被忽略,.Verb设置为runas,因为.WorkingDirectory实际上并没有设置工作目录,而是指定在何处查找可执行文件(如果通过名称指定)只是 - 然而,仍然执行%PATH% / $env:PATH中的查找。
  • 虽然将命令传递给调用的shell的/c参数也适用于PowerShell的CLI,但PowerShell通常使用sigil -为参数名称添加前缀;从而, -c-Command的简称)是更好的选择。 另外,鉴于PowerShell默认加载其$PROFILE初始化文件(即使使用-Command-File调用,即使这通常是不合需要的),最好使用-NoProfile -Command ...代替。
  • 通常 - 如果您不需要提升(作为管理员运行) - 作为 - 慢速 - 通过powershell.exe创建子进程的替代方法,请考虑使用PowerShell SDK (API),这样可以加快进程内执行速度,同时还可以实现更好的处理能力 - 输出流的捕获(在您的特定场景中您似乎并不感兴趣;而System.Diagnostics.ProcessStartInfo允许您通过.RedirectStandardOutput.RedirectStandardError属性捕获stdout和stderr输出,请注意PowerShell具有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();

2
投票

只需更改行:

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

至:

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

这将使您的软件打开powershell.exe而不是cmd.exe,我不知道这是否是最好的方式,但我试过这里,它对我有用。

© www.soinside.com 2019 - 2024. All rights reserved.