Дождитесь завершения всех дочерних процессов - PullRequest
0 голосов
/ 20 октября 2018

В настоящее время я пытаюсь запустить скрипт несколько раз и позволить родителю дождаться завершения всех дочерних процессов.

Создание дочерних процессов выглядит следующим образом:

# Spawn balance load processes
$command = "-i $ScriptPath\balanceLoaders\%BALANCE_DIR% -o $outputDirectory -c %BALANCE_DIR%"
#$command = "$ScriptPath\convertFiles.ps1 -i $ScriptPath\balanceLoaders\%BALANCE_DIR% -o $outputDirectory -c %BALANCE_DIR%"
for ([int]$i = 0; $i -lt $b; $i++) {
    #$proc = Start-Process powershell.exe -WindowStyle Hidden -Argument $command.Replace('%BALANCE_DIR%', $i) -PassThru
    $proc = Start-Process $ScriptPath\convertfiles.exe -WindowStyle Hidden -Verb Runas -ArgumentList $command.Replace('%BALANCE_DIR%', $i) -PassThru
}

Дети рождаются динамически.В настоящее время я могу отслеживать только последнего порожденного ребенка с $proc.Однако я хочу отследить их все.

В настоящее время используется $proc.WaitForExit() для ожидания ребенка.

Ответы [ 2 ]

0 голосов
/ 21 октября 2018

Полезный ответ Ансгара Вихера содержит хорошие указатели и рабочее решение, но , если вы просто хотите дождаться завершения всех порожденных процессов, используйте Wait-Processпроще .

При этом , если вы хотите проверить коды выхода по мере их появления до того, как все процессы завершатся, циклнеобходимо периодически (Start-Sleep), как в ответе Ансгара, необходимо .

Следующее решение демонстрирует метод синхронного ожидания для всех с Wait-Process супрощенный пример, который создает 3 экземпляра Блокнота и ожидает завершения всех из них:

# Create all processes and store objects representing them in array $procs.
$b = 3 # number of processes to create
$procs = foreach ($i in 0..($b-1)) { Start-Process -PassThru Notepad }

# Wait for all processes to exit.
# (Close the Notepad windows manually or, if no Notepad windows were previously
# open, use `Stop-Process -Name Notepad` from another session to forcefully close them.)
# Use Wait-Process -Timeout <secs> to limit the max. period of time to wait.
$procs | Wait-Process 

# Get the exit codes.
$exitCodes = $procs.ExitCode # PSv3+; v2: $procs | Select-Object -ExpandProperty ExitCode

Или, как один конвейер:

# Use $_ inside { ... } to refer to the current iteration value.
# Use $procs.ExitCode to get the exit codes.
0..($b-1) | ForEach-Object -ov procs { Start-Process -PassThru Notepad } | Wait-Process

Обратите внимание на использование -ov- сокращение от общего параметра -OutVariable, который собирает объекты процесса, выводимые вызовами блока сценария ForEach-Object командлета.

0 голосов
/ 20 октября 2018

Соберите все процессы в массив и запускайте цикл ожидания до тех пор, пока все они не завершатся.

$proc = for ($i = 0; $i -lt $b; $i++) {
    Start-Process ... -PassThru
}

while (($proc | Select-Object -Expand HasExited) -contains $false) {
    Start-Sleep -Milliseconds 100
}

Если у вас PowerShell v3 или новее, вы можете упростить цикл примерно до следующего:

while ($proc.HasExited -contains $false) {
    Start-Sleep -Milliseconds 100
}

, поскольку PowerShell v3 представил новую функцию под названием перечисление членов , которая позволяет получать доступ к свойствам или методам элементов массива через объект массива.

...