9

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.

Martin Brandl
  • 56,134
  • 13
  • 133
  • 172
Tehc
  • 669
  • 3
  • 10
  • 28

2 Answers2

18

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
}
Martin Brandl
  • 56,134
  • 13
  • 133
  • 172
  • Thank you for the fast answer. So if i give my Jobs individual names and then use the Get-Job -Name cmdlet i can create a custom message to print out once the Job has been completed, even though it takes a few hours? Or would i have to make a Loop that continuously checks every 5 minutes if it's completed? – Tehc Aug 12 '16 at 07:30
  • You could also let the job himself output a message after he is finished – Martin Brandl Aug 12 '16 at 07:42
  • That would be the perfect solution but how would i do that? i tried it by putting a write-host message behind my .cmd file but it just imidiatly printed the message, even though the Job hasn't finished yet. – Tehc Aug 12 '16 at 07:46
  • I found a better solution, see my edited answer. I think thats the best way to do that – Martin Brandl Aug 12 '16 at 07:47
  • Thank you so much! This is amazing, just what i searched for. – Tehc Aug 12 '16 at 07:49
  • 1
    `$jobEvent | Unregister-Event` does not seem to work the way I believe you intended it. After running this example, there is still a job in running state. – René Nyffenegger Dec 17 '20 at 09:28
  • @MartinBrandl I was trying to use the above code. $job gets perfectly removed. However, I see that jobEvent still keeps "Running". Is there a way the jobEvent can be removed too? – Ribu Oct 27 '22 at 02:34
5

Multiple possible ways here:

$Var = Start-Job { & K:\sample\kdp.cmd }

an then check

$Var.State

Or give the job a name

Start-Job { & K:\sample\kdp.cmd } -Name MyJob

and then check

Get-Job MyJob
oɔɯǝɹ
  • 7,219
  • 7
  • 58
  • 69
whatever
  • 871
  • 4
  • 11