1. ホーム
  2. powershell

[解決済み] Powershell プロセスの開始、タイムアウトによる待機、Kill、終了コードの取得

2022-03-11 13:30:02

質問

あるプログラムをループで繰り返し実行したい。

時々、プログラムがクラッシュするので、次の繰り返しが正しく開始できるように、プログラムを終了させたいと思います。私はこれをタイムアウトによって決定する。

タイムアウトは機能していますが、プログラムのExit Codeを取得することができません。

以前は、タイムアウトで待たずに、Start-Processで-waitを使うだけでしたが、これだと起動したプログラムがクラッシュするとスクリプトがハングしてしまいます。しかし、この設定では、終了コードを正しく取得することができました。

ISEから実行しています。

for ($i=0; $i -le $max_iterations; $i++)
{
    $proc = Start-Process -filePath $programtorun -ArgumentList $argumentlist -workingdirectory $programtorunpath -PassThru
    # wait up to x seconds for normal termination
    Wait-Process -Timeout 300 -Name $programname
    # if not exited, kill process
    if(!$proc.hasExited) {
        echo "kill the process"
        #$proc.Kill() <- not working if proc is crashed
        Start-Process -filePath "taskkill.exe" -Wait -ArgumentList '/F', '/IM', $fullprogramname
    }
    # this is where I want to use exit code but it comes in empty
    if ($proc.ExitCode -ne 0) {
       # update internal error counters based on result
    }
}

どうすれば

  1. プロセスの開始
  2. 順番に実行され、終了するのを待つ
  3. クラッシュした場合(例:タイムアウトになった場合)、Killする。
  4. プロセスの終了コードを取得する

解決方法は?

を使用すると、より簡単にプロセスを終了させることができます。 $proc | kill または $proc.Kill() . この場合、終了コードを取得することができないので、むしろ内部のエラーカウンターを更新する必要があることに注意してください。

for ($i=0; $i -le $max_iterations; $i++)
{
    $proc = Start-Process -filePath $programtorun -ArgumentList $argumentlist -workingdirectory $programtorunpath -PassThru

    # keep track of timeout event
    $timeouted = $null # reset any previously set timeout

    # wait up to x seconds for normal termination
    $proc | Wait-Process -Timeout 4 -ErrorAction SilentlyContinue -ErrorVariable timeouted

    if ($timeouted)
    {
        # terminate the process
        $proc | kill

        # update internal error counter
    }
    elseif ($proc.ExitCode -ne 0)
    {
        # update internal error counter
    }
}