Powershell code runs synchronously. This means that one line is processed at a time until the end of the script is reached.
This is fine for most scripts but there will be situations where this type of execution is not ideal. A port scanner for example would take forever if it ran synchronously.
When creating a script that may potentially take a long time to run, you have other options. You can instead choose to execute code asynchronously with a concept called jobs. In PowerShell, a job is a piece of code that is executed in the background. It’s code that starts but then immediately returns control to PowerShell to continue processing other code. Jobs are great for performance and when a script doesn’t depend on the results of prior code execution.
Lets take a look at the following piece of code.
$IPToScan = "192.168.0.2"
Start-Job -Name PingTest -Scriptblock {
param($TargetIP)
test-connection $TargetIP -Count 1 -ErrorAction SilentlyContinue > $Null
if ($?)
{
return $TargetIP + " is OK"
}else{
return $TargetIP + " is dead"
}
} -Arg $IPToScan
Here I am creating and running a job called PingTest.
The code for Ping Test is every thing in the scriptblock (Lines 4 – 13)
My PingTest scriptblock will take the argument $IPToScan as defined in line 14.
Inside the scriptblock that argument is referenced as $TargetIP
I Ping that IP $TargetIP in line 7 but the test-connection command is set to return nothing (-ErrorAction SilentlyContinue > $Null) I do not want the command to return anything.
Next I test whether the test-connection command was successful or not using the $? variable (there are many ways to do this). Depending on the result is what I want the job to return. I did not really need to use the return command but it makes the line easy to understand.
So if I run the code I get the following
The last part of the above is the output of the script. It shows the job is running in the back ground and has an ID of 1. Powershell jobs run with an odd number 1,3,5, etc.
If I wait a couple of seconds and then run the command get-job. I get the following.
The job State has changed to completed.
I can now run the command Receive-job with the job number to the $jobResult variable.
But if I now do a get-job again I see something different.
The HasMoreData attribute has changed from true to False.
So if I do a Recive-job 1 again….
I don’t get any output.
If I want to keep the job output then I sent it to a variable like I did when I run:
$jobResult = receive-job 1
Or I could have used the -keep switch
$jobResult = receive-job 1 -keep
But regardless of whether I keep the data in the job or copy it out to a variable and work with it, I will need to remove the job.
To do that I issue the command remove-job 1
That is Powershell jobs in a nutshell.
In Part 2 I will show how to manage jobs.
In Part 3 I will dig more in to getting data out of jobs