我有一个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。我将如何更改此功能以适应新代码。这仍然是最有效的方式吗?
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
中的查找。/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();
只需更改行:
proc.FileName = @"C:\Windows\System32\cmd.exe";
至:
proc.FileName = @"C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe";
这将使您的软件打开powershell.exe而不是cmd.exe,我不知道这是否是最好的方式,但我试过这里,它对我有用。