Как заставить PowerShell ждать завершения каждой команды, прежде чем начинать следующую? - PullRequest
178 голосов
/ 16 ноября 2009

У меня есть скрипт PowerShell 1.0, чтобы просто открыть кучу приложений. Первая - это виртуальная машина, а остальные - приложения для разработки. Я хочу, чтобы виртуальная машина завершила загрузку до открытия остальных приложений.

В bash я мог бы просто сказать "cmd1 && cmd2"

Вот что у меня есть ...

C:\Applications\VirtualBox\vboxmanage startvm superdooper
    &"C:\Applications\NetBeans 6.5\bin\netbeans.exe"

Ответы [ 7 ]

316 голосов
/ 16 ноября 2009

Обычно для внутренних команд PowerShell ожидает перед началом следующей команды. Единственным исключением из этого правила является EXE-файл на основе внешней подсистемы Windows. Первый трюк состоит в том, чтобы передать Out-Null следующим образом:

Notepad.exe | Out-Null

PowerShell будет ожидать завершения процесса Notepad.exe, прежде чем продолжить. Это изящно, но довольно тонко, чтобы разобраться с чтением кода. Вы также можете использовать Start-Process с параметром -Wait:

Start-Process <path to exe> -NoNewWindow -Wait

Если вы используете версию PowerShell Community Extensions, это:

$proc = Start-Process <path to exe> -NoWindow
$proc.WaitForExit()

Другой вариант в PowerShell 2.0 - использовать фоновое задание:

$job = Start-Job { invoke command here }
Wait-Job $job
Receive-Job $job
44 голосов
/ 01 сентября 2011

Помимо использования Start-Process -Wait, передача вывода исполняемого файла заставит Powershell ждать. В зависимости от необходимости я, как правило, отправляю по трубам Out-Null, Out-Default, Out-String или Out-String -Stream. Здесь - это длинный список некоторых других параметров вывода.

# 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, на которые вы ссылались (&, &&, ||). Это Кажется, мы должны быть более многословными с Powershell .

11 голосов
/ 27 июня 2014

Просто используйте «Wait-process»:

"notepad","calc","wmplayer" | ForEach-Object {Start-Process $_} | Wait-Process ;dir

работа выполнена

6 голосов
/ 20 февраля 2013

Если вы используете Start-Process <path to exe> -NoNewWindow -Wait

Вы также можете использовать опцию -PassThru для вывода эхосигнала.

5 голосов
/ 26 марта 2014

Некоторые программы не могут обрабатывать поток вывода очень хорошо, использование канала для Out-Null может не блокировать его.
И Start-Process нужен переключатель -ArgumentList для передачи аргументов, что не очень удобно.
Есть и другой подход.

$exitCode = [Diagnostics.Process]::Start(<process>,<arguments>).WaitForExit(<timeout>)
2 голосов
/ 31 декабря 2014

Включая опцию -NoNewWindow выдает ошибку: Start-Process : This command cannot be executed due to the error: Access is denied.

Единственный способ заставить его работать - позвонить:

Start-Process <path to exe> -Wait
0 голосов
/ 11 апреля 2018

Пройдя дальше, вы можете даже разобрать на лету

, например

& "my.exe" | %{
    if ($_ -match 'OK')
    { Write-Host $_ -f Green }
    else if ($_ -match 'FAIL|ERROR')
    { Write-Host $_ -f Red }
    else 
    { Write-Host $_ }
}
...