我有一个 PowerShell 1.0 脚本来打开一堆应用程序。第一个是虚拟机,其他是开发应用程序。我希望虚拟机在其余应用程序打开之前完成启动。
在 bash 中我只能说 "cmd1 && cmd2"
这就是我所拥有的...
C:\Applications\VirtualBox\vboxmanage startvm superdooper
&"C:\Applications\NetBeans 6.5\bin\netbeans.exe"
通常,对于内部命令,PowerShell 会在开始下一个命令之前等待。此规则的一个例外是基于外部 Windows 子系统的 EXE。第一个技巧是像这样流水线到 Out-Null
:
Notepad.exe | Out-Null
PowerShell 将等到 Notepad.exe 进程退出后再继续。从阅读代码中可以看出这很漂亮,但有点微妙。您还可以将 Start-Process
与 -Wait
参数一起使用:
Start-Process <path to exe> -NoNewWindow -Wait
如果您使用的是 PowerShell 社区扩展版本,则为:
$proc = Start-Process <path to exe> -NoNewWindow -PassThru
$proc.WaitForExit()
PowerShell 2.0 中的另一个选项是使用 background job:
$job = Start-Job { invoke command here }
Wait-Job $job
Receive-Job $job
除了使用 Start-Process -Wait
之外,通过管道传输可执行文件的输出将使 Powershell 等待。根据需要,我通常会通过管道传输到 Out-Null
、Out-Default
、Out-String
或 Out-String -Stream
。 Here 是一些其他输出选项的长列表。
# Saving output as a string to a variable.
$output = ping.exe example.com | Out-String
# Filtering the output.
ping stackoverflow.com | where { $_ -match '^reply' }
# Using Start-Process affords the most control.
Start-Process -Wait SomeExecutable.com
我确实想念您引用的 CMD/Bash 样式运算符(&、&&、||)。看来我们必须是more verbose with Powershell。
Out-String
将输出 更改为 单行 字符串,而 PowerShell 默认返回一个行数组。控制台应用程序应避免使用 Start-Process
(除非您确实想在 新窗口 中运行它们),因为您将无法捕获或重定向它们的输出。
只需使用“等待过程”:
"notepad","calc","wmplayer" | ForEach-Object {Start-Process $_} | Wait-Process ;dir
工作完成
如果您使用 Start-Process <path to exe> -NoNewWindow -Wait
您还可以使用 -PassThru
选项来回显输出。
-PassThru
不会回显 output(根据定义,非控制台应用程序不会产生控制台输出),它会输出代表新启动进程的 System.Diagnostics.Process
实例,因此您可以检查它的属性并等待它稍后退出。
有些程序不能很好地处理输出流,使用管道到 Out-Null
可能不会阻塞它。
而 Start-Process
需要 -ArgumentList
开关来传递参数,不太方便。
还有一个方法。
$exitCode = [Diagnostics.Process]::Start(<process>,<arguments>).WaitForExit(<timeout>)
包含选项 -NoNewWindow
会给我一个错误:Start-Process : This command cannot be executed due to the error: Access is denied.
我可以让它工作的唯一方法是打电话:
Start-Process <path to exe> -Wait
更进一步,您甚至可以动态解析
例如
& "my.exe" | %{
if ($_ -match 'OK')
{ Write-Host $_ -f Green }
else if ($_ -match 'FAIL|ERROR')
{ Write-Host $_ -f Red }
else
{ Write-Host $_ }
}
总是有cmd。
cmd /c start /wait notepad
或者
notepad | out-host
| out-null
做了我需要的。尝试使用Start-Job
但因为我将函数的结果作为参数传递,它对我来说有点小气,所以我不能使用最后一个建议......-ArgumentList
传递多个参数,请使用-ArgumentList /D=test,/S
等逗号分隔它们。