【问题标题】:Wait for process to end等待进程结束
【发布时间】:2013-12-03 08:38:12
【问题描述】:

我有一个 powershell 脚本,它会自动打印 Foxit 文件夹中的所有 .pdf 文件。我将它设置为等到 Foxit 退出,直到脚本继续。每隔一段时间,即使 Foxit 已经退出,脚本也会暂停并等待。有没有办法让它在一定时间后超时?

这是我的代码:

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

我已经尝试了here 的建议,但它们似乎不起作用。例如,如果我这样做:

$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.

任何帮助将不胜感激。

【问题讨论】:

    标签: powershell powershell-4.0


    【解决方案1】:

    我想我明白了。如果我以Invoke-WmiMethod 开头,我可以获取进程ID 并等待它,然后让它超时。

    $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
    

    这似乎工作得相当一致。

    【讨论】:

      【解决方案2】:

      实现超时的一种方法是使用后台作业:

      $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
      

      【讨论】:

      • 使用后台工作不适合我。我不确定为什么,但我认为这与未传递给工作的变量有关。
      【解决方案3】:

      我遇到了同样的问题,发现了一个轻微的simpler solution,它也捕获了子进程的输出。 -PassThru 参数是关键,因为它为 cmdlet 启动的每个进程返回一个进程对象。

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

      【讨论】:

        【解决方案4】:

        我更喜欢这种风格,以便更好地控制外部进程运行时要做什么:

        $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 属性,我可以继续处理我的代码,同时执行任何其他并行任务。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2018-11-25
          • 2015-10-25
          • 1970-01-01
          • 2012-07-13
          相关资源
          最近更新 更多