Дождаться окончания процесса

У меня есть скрипт powershell, который автоматически печатает все файлы.pdf в папке с Foxit. Я установил ожидание выхода Foxit, пока сценарий не продолжится. Время от времени скрипт останавливается и ждет, даже если Foxit уже вышел. Есть ли способ сделать это тайм-аут после определенного количества времени?

Вот код, который у меня есть:

Start-Process $foxit -ArgumentList $argument -Wait
Move-Item $filePath $printed[$location]
Add-Content "$printLogDir\$logFileName" $logEntry

Я попробовал рекомендации здесь, и они, кажется, не работают. Например, если я делаю:

$proc = Start-Process $foxit -ArgumentList $argument
$proc.WaitForExit()
Move-Item $filePath $printed[$location]
Add-Content "$printLogDir\$logFileName" $logEntry

Я получил:

You cannot call a method on a null-valued expression.

Любая помощь будет принята с благодарностью.

3 ответа

Решение

Я думаю, что я понял это. Если я начну с Invoke-WmiMethod Я могу получить идентификатор процесса и дождаться его, а затем попросить перевести его на тайм-аут.

$proc = Invoke-WmiMethod -Class win32_process -Name create -ArgumentList "$foxit $argument"
Wait-Process -Id $proc.ProcessId -Timeout 120
Move-Item $filePath $printed[$location]
Add-Content "$printLogDir\$logFileName" $logEntry

Это, кажется, работает довольно последовательно.

Один из способов реализовать тайм-аут - использовать фоновое задание:

$Job = start-job -ScriptBlock { write-output 'start';Start-Sleep -Seconds 15 }

$timeout = New-TimeSpan -Seconds 10
$timer = [diagnostics.stopwatch]::StartNew()

  While ($timer.Elapsed -le $timeout)
   {
    if ($Job.State -eq 'Completed' )
     {
      Receive-Job $Job
      Remove-Job  $Job
      Return
     } 
     Start-Sleep -Seconds 1
    } 
      write-warning 'Job timed out.  Stopping job'
      Stop-Job $Job
      Receive-Job $Job
      Remove-Job  $Job

Я столкнулся с этой же проблемой и нашел немного более простое решение, которое также фиксирует выходные данные дочернего процесса. -PassThru Аргумент является ключевым, поскольку он возвращает объект процесса для каждого процесса, запускаемого командлетом.

$proc = Start-Process $foxit -ArgumentList $argument -PassThru
Wait-Process -Id $proc.Id -Timeout 120
Move-Item $filePath $printed[$location]
Add-Content "$printLogDir\$logFileName" $logEntry

Я предпочитаю этот стиль, чтобы лучше контролировать, что делать во время выполнения внешнего процесса:

$waitTime = 60
$dism = Start-Process "$env:windir\system32\dism.exe" -ArgumentList "/Online /Cleanup-Image /ScanHealth" -PassThru -WindowStyle Hidden
while (!$dism.HasExited -or $waitTime -gt 0) {sleep -Seconds 1; $waitTime--}
"done."

Установив флажок для атрибута HasExited, я могу продолжить свой код параллельно с любыми другими задачами.

Другие вопросы по тегам