2

I want to run a script when a PowerShell job has successfully completed. But how do I find out all possible events of the job started with the Start-Job cmdlet?

Here is an example:

$myjob = Start-Job { Get-ChildItem }

$jobEvent = Register-ObjectEvent -InputObject $myjob -EventName StateChanged -Action {
    Write-Host 'Job has completed'
}

So from some other examples on Stack Overflow I know that there is StateChanged event, but it only tells that a state of a job has changed. Is there any event that would tell that the job has failed or completed successfully?

How do I get a list of such events? Is there any event besides StateChanged?

Or does the code have to inspect the job using Get-Job after receiving the StateChanged event to determine the job's actual state?

bahrep
  • 29,961
  • 12
  • 103
  • 150

1 Answers1

2

StateChanged is the only event you can subscribe to for the Job Class, it is enough though for what you're looking to accomplish.

In the Action block of your event there are different automatic variable that get automatically populated at event trigger: $Event, $EventArgs, $args, $EventSubscriber and $Sender which you can use to determine if your Job completed successfully or not. See about Automatic Variables for more details.

In this case I believe you could use the JobState.State Property from your Job and check if its equal to Completed. You could also check the .Reason property in case of a failure though this property may not always be populated.

$jobEvent = Register-ObjectEvent -InputObject $myjob -EventName StateChanged -Action {
    switch($EventArgs.JobStateInfo.State) {
        Completed { Write-Host ('Job [{0}] completed successfully.' -f $sender.InstanceId) -ForegroundColor Green }
        Failed { Write-Host ('Job [{0}] failed.' -f $sender.InstanceId) -ForegroundColor Red }
        Default { <# something else here, enum has many possible states #> }
    }
}
mklement0
  • 382,024
  • 64
  • 607
  • 775
Santiago Squarzon
  • 41,465
  • 5
  • 14
  • 37
  • @mklement0 my thought was any of the states in the `enum` could trigger the event but tbh I dont know – Santiago Squarzon Jan 29 '23 at 20:27
  • @mklement0 to be fair, after some testing, can't even get jobs to be in those states so you're most likely right – Santiago Squarzon Jan 29 '23 at 20:54
  • 1
    Hmmm... at least at first glance I see no attempt to filter regarding what states trigger an event: https://github.com/PowerShell/PowerShell/blob/f8cbf90ccb7930e23c7f938256c3f361b3384ad5/src/System.Management.Automation/engine/remoting/client/Job.cs#L1380 (look for `StateChanged.SafeInvoke(`) – mklement0 Jan 29 '23 at 21:04
  • 1
    I went _partway_ down the rabbit hole: `NotRunning` is the _initial_ state and therefore never reported. All others do seem to be reported, including `Running` - assuming you subscribe in time; with `Start-Job`, it's usually too late, but with `Start-ThreadJob` you do see this state change. `Stopping` (as opposed to `Stopped`) is seemingly only raised if the job has _child_ jobs. Not sure about `Suspending`, which seems to relate to WinPS-only workflows. – mklement0 Jan 29 '23 at 22:50
  • 1
    @mklement0 thats good to know I guessed some of them could be hard to trigger due to timing, might be worth adding an answer with this additional information – Santiago Squarzon Jan 29 '23 at 23:13