将运行 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 的 CLI,PowerShell 通常使用 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();
我有一个 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,我不知道这是否是解决此问题的最佳方法,但我在这里尝试过并且对我有用。
除非存在安全问题(有人将非标准的恶意
的非标准 Windows 安装的问题cmd.exe
/powershell.exe
可执行文件放在%PATH%
/$env:PATH
抢占标准可执行文件的环境变量),单独使用可执行文件 文件名 更简单,即仅cmd.exe
/powershell.exe
- 这也避免了根为 notC:\Windows
.- 此外,鉴于 您通过
.FileName
指定了 完整路径 ,.WorkingDirectory
属性 是有效地 忽略 并将.Verb
设置为runas
,因为.WorkingDirectory
实际上并没有 设置工作目录,但指定在哪里可以找到可执行文件,如果指定仅按名称 - 然而,在%PATH%
中查找/$env:PATH
仍在执行。
- 此外,鉴于 您通过
虽然将命令传递给 shell 调用的
/c
参数恰好也适用于 PowerShell 的 CLI,PowerShell 通常使用 sigil-
作为参数名称的前缀;因此,-c
(-Command
的缩写)是更好的选择。- 此外,假定 PowerShell 默认加载其
$PROFILE
初始化文件 (即使使用-Command
或-File
调用时,即使这通常是不可取的),最好使用-NoProfile -Command ...
。
- 此外,假定 PowerShell 默认加载其
一般 - 如果您不需要需要海拔 (运行 作为 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();