Powershell Start Process, Wait with Timeout, Kill and Get Exit Code

Andreas Reiff picture Andreas Reiff · Apr 29, 2016 · Viewed 27.7k times · Source

I want to repeatedly execute a program in a loop.

Sometimes, the program crashes, so I want to kill it so the next iteration can correctly start. I determine this via timeout.

I have the timeout working but cannot get the Exit Code of the program, which I also need to determine its result.

Before, I did not wait with timeout, but just used -wait in Start-Process, but this made the script hang if the started program crashed. With this setup I could correctly get the exit code though.

I am executing from 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
    }
}

How can I

  1. Start a process
  2. Wait for it to orderly execute and finish
  3. Kill it if it is crashed (e. g. hits timeout)
  4. get exit code of process

Answer

Martin Brandl picture Martin Brandl · Apr 29, 2016

You can terminate the process more simply using $proc | kill or $proc.Kill(). Be aware, that you won't be able to retrieve a exit code in this case, you should rather just update the internal error counter:

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
    }
}