How to do something if a job has finished

Byakko_Haku picture Byakko_Haku · Aug 12, 2016 · Viewed 8k times · Source

I'm trying to implement a GUI to my PowerShell script to simplify a certain process for other users. I have following PowerShell script:

if ($checkBox1.Checked)    { 
    Try{
    Start-Job { & K:\sample\adp.cmd }
    $listBox1.Items.Add("ADP-Job started...")
    }catch [System.Exception]{
    $listBox1.Items.Add("ADP --> .cmd File not found!")}
    }

    if ($checkBox2.Checked)    { 
    Try{ 
    Start-Job { & K:\sample\kdp.cmd }
    $listBox1.Items.Add("KDP-Job started...")
    }catch [System.Exception]{
    $listBox1.Items.Add("KDP --> .cmd File not found!")}
    }

Is there a way to continuously check all running Jobs and do something for each Job that has finished? For Example to print out something like this in my listbox: ADP-Files have been uploaded

Since each Job takes around 5 minutes - 4 hours I thought of a while Loop that checks every 5 minutes if a Job is finished, but I can't figure out how to distinguish each Job to do something specific.

Answer

Martin Brandl picture Martin Brandl · Aug 12, 2016

You can either specifiy a name for the job using the -Name parameter:

Start-Job { Write-Host "hello"} -Name "HelloWriter"

And receive the job status using the Get-Job cmdlet:

Get-Job -Name HelloWriter

Output:

Id     Name            PSJobTypeName   State         HasMoreData     Location             Command                  
--     ----            -------------   -----         -----------     --------             -------                  
3      HelloWriter     BackgroundJob   Completed     True            localhost             Write-Host "hello"

Or you assign the Start-Job cmdlet to a variable and use it to retrieve the job:

$worldJob = Start-Job { Write-Host "world"}

So you can just write $woldJob and receive:

Id     Name            PSJobTypeName   State         HasMoreData     Location             Command                  
--     ----            -------------   -----         -----------     --------             -------                  
7      Job7            BackgroundJob   Completed     True            localhost             Write-Host "world" 

You also don't have to poll the Job state. Instead use the Register-ObjectEvent cmdlet to get notificated when the job has finished:

$job = Start-Job { Sleep 3; } -Name "HelloJob"

$jobEvent = Register-ObjectEvent $job StateChanged -Action {
    Write-Host ('Job #{0} ({1}) complete.' -f $sender.Id, $sender.Name)
    $jobEvent | Unregister-Event
}