Search code examples
powershellwaitexit-codestart-process

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


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

Solution

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