简体   繁体   English

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

[英]Converting C# Application that runs CMD commands to one that runs Powershell commands with administrative privileges

I have a Visual studio Application that runs a series of Cmd commands using the following function 我有一个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();
    }

We recently updated our Code and converted to Powershell. 我们最近更新了代码,并转换为Powershell。 How would I go about changing this function to accommodate for the new code. 我将如何更改此功能以适应新代码。 Is this still the most efficient way to go??? 这仍然是最有效的方法吗???

Just change the line: 只需更改行:

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

To: 至:

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

This will make your software open powershell.exe instead of cmd.exe, I can't tell if that is the best way to go about this but I tried here and it worked for me. 这将使您的软件打开powershell.exe而不是cmd.exe,我无法确定这是否是解决此问题的最佳方法,但是我在这里尝试了一下,并且对我有用。

Otávio Caldonazo's helpful answer provides an effective solution, but it's worth explaining a few things: 奥塔维奥·卡尔多纳佐(OtávioCaldonazo)的有用答案提供了有效的解决方案,但值得解释以下几点:

  • Unless there are security concerns (someone having placed a nonstandard, malicious cmd.exe / powershell.exe executable in a folder listed in the %PATH% / $env:PATH environment variable that preempts the standard executables), it is simpler to use the executable file name alone, ie, just cmd.exe / powershell.exe - this also avoids problems with non-standard Windows installations whose root is not C:\\Windows . 除非有安全方面的考虑(有人将非标准的恶意cmd.exe / powershell.exe可执行文件放在%PATH% / $env:PATH环境变量中列出的文件夹中,这些文件优先于标准可执行文件),否则使用仅可执行文件名 ,即cmd.exe / powershell.exe这还避免了根不是 C:\\Windows的非标准Windows安装的问题。

    • Also, given that you're specifying a full path via .FileName , the .WorkingDirectory property is effectively ignored with .Verb set to runas , because .WorkingDirectory then doesn't actually set the working directory , but specifies where to find the executable , if specified by name only - however, lookups in %PATH% / $env:PATH are still performed. 此外,考虑到你指定通过全路径 .FileName ,该.WorkingDirectory财产与忽略 .Verb设置为runas ,因为.WorkingDirectory那么实际上并没有设置工作目录 ,而是指定在哪里查找可执行文件 ,如果仅按名称指定-但是,仍会执行%PATH% / $env:PATH中的查找。
  • While the /c parameter to pass a command to the shell invoked happens to work with PowerShell's CLI too, PowerShell generally use sigil - to prefix parameter names ; 虽然/c参数传递一个命令来调用的外壳会发生使用PowerShell的命令行工作过,PowerShell的一般使用印记-以前缀参数名称 ; thus, 从而,
    -c (short for -Command ) is the better choice. -c-Command )是更好的选择。

    • Additionally, given that PowerShell loads its $PROFILE initialization file by default (even when invoked with -Command or -File , even though that is generally undesirable), it's best to use -NoProfile -Command ... instead. 此外,考虑到PowerShell中加载其$PROFILE 默认初始化文件(即使与调用-Command-File ,尽管这通常是不希望), 最好使用-NoProfile -Command ...代替。
  • Generally - if you don't need elevation (running as an admin ) - as an alternative to the - slow - creation of a child process via powershell.exe , consider use of the 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 ). 一般 -如果你不需要 海拔 (运行作为管理员 ) -作为替代-慢-通过创建子进程powershell.exe ,考虑使用的PowerShell的SDK(API) ,实现了更高的进程执行,同时还可以实现更细粒度的输出流捕获 (您似乎对特定场景不感兴趣;而System.Diagnostics.ProcessStartInfo允许您通过.RedirectStandardOutput.RedirectStandardError属性捕获stdout和stderr输出,请注意,PowerShell具有其他输出流 )。

Based on the above, I suggest doing the following: 基于以上内容,我建议您执行以下操作:

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

Or, more concisely: 或者,更简洁地说:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM