Killing Long-Running Scripts

by Apr 19, 2012

You can use a background thread to monitor how long a script is running, and then kill that script if it takes too long. You can even write to an event log or send off a mail before the script is killed.

Here's how you implement such a time bomb: To set a maximum runtime, use Start-Timebomb like this:

PS> Start-Timebomb -Seconds 30

After 30 seconds, the script will be killed unless you call Stop-Timebomb in time. Start-Timebomb supports the parameter -Action that accepts a script block. This is the code that gets executed after time is up, so here you could also write to event logs or simply output a benign warning:

PS> Start-Timebomb -Seconds 30 -Action { [System.Console]::Write('Your breakfast egg is done, get it now!') }

Note though that because the timebomb is running in another thread, you cannot output data to the foreground thread. That's why the sample used the type System.Console to write directly into the console window.

And here are the two functions:

function Start-Timebomb {
  param(
    [Int32]
    $Seconds,
    
    [ScriptBlock]
    $Action = { Stop-Process -Id $PID }
  )
  
  $Wait = "Start-Sleep -seconds $seconds"
  $script:newPowerShell = [PowerShell]::Create().AddScript($Wait).AddScript($Action)
  $handle = $newPowerShell.BeginInvoke()
  Write-Warning "Timebomb is active and will go off in $Seconds seconds unless you call Stop-Timebomb before."
}

function Stop-Timebomb {
  if ( $script:newPowerShell -ne $null) {
    Write-Host 'Trying to stop timebomb...' -NoNewline
    $script:newPowerShell.Stop()
    $script:newPowerShell.Runspace.Close()
    $script:newPowerShell.Dispose()
    Remove-Variable newPowerShell -Scope script
    Write-Host 'Done!'
  } else {
    Write-Warning 'No timebomb found.'
  }
}

Twitter This Tip! ReTweet this Tip!