我有一个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。我将如何更改此功能以适应新代码。这仍然是最有效的方法吗?
答案 0 :(得分:2)
只需更改行:
proc.FileName = @"C:\Windows\System32\cmd.exe";
收件人:
proc.FileName = @"C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe";
这将使您的软件打开powershell.exe而不是cmd.exe,我无法确定这是否是解决此问题的最佳方法,但我在这里尝试了,并且对我有效。
答案 1 :(得分:0)
Otávio Caldonazo's helpful answer提供了有效的解决方案,但值得解释以下几点:
除非存在安全隐患(有人将非标准的恶意cmd.exe
/ powershell.exe
可执行文件放置在%PATH%
/ $env:PATH
环境变量中列出的文件夹中优先使用标准可执行文件),单独使用可执行文件文件名(即仅cmd.exe
/ powershell.exe
会更简单-这也避免了根为 not C:\Windows
的非标准Windows安装出现问题。
.FileName
指定了完整路径,则.WorkingDirectory
属性实际上会被{em> 忽略,{ {1}}设置为.Verb
,因为runas
实际上并不 设置工作目录,而是指定在哪里找到可执行文件< / em>,如果仅按名称指定 -但是,仍会在.WorkingDirectory
/ %PATH%
中进行查找。虽然$env:PATH
参数将命令传递给所调用的外壳程序也恰好与PowerShell的 CLI 一起使用,但 PowerShell通常也使用sigil /c
前缀参数名称;因此,
-
(-c
的缩写)是更好的选择。
-Command
初始化文件 (即使使用$PROFILE
或-Command
进行调用,即使通常不希望这样做) ,最好改用-File
。 通常-如果您不需要需要海拔(以 admin 身份运行) >)-作为通过-NoProfile -Command ...
缓慢创建子进程的替代方法,请考虑使用PowerShell SDK (API) ,这样可以更快地实现 执行中执行,同时还可以更细粒度地捕获输出流 (您似乎对此并不感兴趣)在您的特定情况下;虽然powershell.exe
允许您通过System.Diagnostics.ProcessStartInfo
和.RedirectStandardOutput
属性捕获stdout和stderr输出,但请注意PowerShell具有additional output streams)。
基于上述内容,我建议您执行以下操作:
.RedirectStandardError
或更简洁地说:
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();