PowerShell Jobs
In this tutorial we will see about PowerShell Jobs. Jobs in PowerShell are running in the background. When you start a background job in PowerShell, it will return immediately to the console. Background jobs run commands and expressions asynchronously. You are able to run cmdlets, functions, scripts and command-based tasks. Background jobs are designed to run commands that take long time to be completed, but you are allowed to run anything. Running commands in PowerShell, you run them synchronously. If the command is run synchronously the PowerShell command prompt is suppressed until the command that you run is completed. A background job does not suppresss the PowerShell prompt.
You are able to continue working in the same session until the background job will finish the job process. Results of the jobs are not provide automatically to the console. You will need to retrieve them manually when they are needed. We will see later in this post how we are able to achieve this. You can also run commands to stop the job, to wait for the job to be completed, and to delete the job. To make the timing of a background job independent of other commands, each background job runs in its own PowerShell environment (a “session”). However, this can be a temporary connection that is created only to run the job and is then destroyed, or it can be a persistent session (a PSSession) that you can use to run several related jobs or commands.
You are able to run background jobs on both local and remote computers. First we need to see the cmdlets that are related to PowerShell jobs in order to help us understand the next sections better.
PowerShell Jobs related cmdlets
Below we will see the cmdlets that are related to PowerShell Jobs along with its description as provided by Microsoft:
Start-Job
– Starts a background job on a local computer.Get-Job
– Gets the background jobs that were started in the current session.Receive-Job
– Gets the results of background jobs.Stop-Job
– Stops a background job.Wait-Job
– Suppresses the command prompt until one or all jobs are complete.Remove-Job
– Deletes a background job.Invoke-Command
– The AsJob parameter runs any command as a background job on a remote computer. You can also useInvoke-Command
to run any job command remotely, including aStart-Job
command.
[adinserter name=”In Article”]
Start a job on local computer
In order to be able to start a background job on our local computer we will need to use Start-Job
cmdlet. The basic syntax of the command that we have to use is the below:
Code:
Start-Job -ScriptBlock {<Commands>}
When we will run the above command, a background job will be created. When we start a job, a job object is created and Start-Job
returns the object to console. The object contains information about the job itself but it does not contain the results of the job.
In the examples below we are running Get-NetAdapter cmdlet as a background job.
Example 1
Code:
Start-Job -ScriptBlock {Get-NetAdapter}
Output:
We are able also to save the object in a variable in order to use this job in other commands.
Example 2
Code:
$MyJob = Start-Job -ScriptBlock {Get-NetAdapter}
Output:
[adinserter name=”In Article”]
Get the current jobs of the session
We are able to get the job object by using Get-Job
cmdlet. If we use Get-Job
cmdlet without any parameters we will retrieve all jobs. You are also able to get the job object only for a specific job. The object can be saved again in a variable to be used in other commands. You can specify a job by Id,Name or Job (variable).
Example 3
Code:
Start-Job -ScriptBlock {Get-NetAdapter} Start-Job -ScriptBlock {Get-Date} Get-Job $MyJob3 = Get-Job -Id 3 $MyJob3
Output:
[adinserter name=”In Article”]
Get the background jobs results
In order to get the results from the job we need to use Receive-Job
cmdlet. Check the below example on how you are able to get the results of the jobs. The below example is based on Example 3
Example 4
Code:
Start-Job -ScriptBlock {Get-NetAdapter} Start-Job -ScriptBlock {Get-Date} Get-Job $MyJob3 = Get-Job -Id 3 $MyJob3 Receive-Job -Id 1 $Job3Results = Receive-Job -Job $MyJob3 $Job3Results
Output:
Note that when you use Receive-Job
you get the results of the job whether is completed or not. If the background job is not completed, you will get only the current results of the job until that moment. By default, Receive-Job
cmdlet deletes the results from the memory when they have been received. If the command was not completed and you run Receive-Job
again it will get the rest of the results only. You are able to keep the results that have been received in the memory by using -Keep
parameter.
Example 5
Code:
Start-Job -ScriptBlock {Get-Process} $MyJob = Get-Job -Id 1 Receive-Job -Job $MyJob
Output:
Example 6
Code:
Start-Job -ScriptBlock {Get-Process} $MyJob = Get-Job -Id 1 Receive-Job -Job $MyJob -Keep
Output:
[adinserter name=”In Article”]
Get the results after the background job finished
As you saw above, I have used Receive-Job
multiple times to get the results. We are able to wait for the job to finish until we will receive the results from the job. By using Wait-Job
, Receive-Job
cmdlet wait for the job to be completed and then it will get the results.
Example 7
Code:
Start-Job -ScriptBlock {Get-NetAdapter} $MyJob = Get-Job -Id 1 Receive-Job -Job $MyJob
Output:
Code:
Start-Job -ScriptBlock {Get-NetAdapter} $MyJob = Get-Job -Id 1 Wait-Job -Job $MyJob Receive-Job -Job $MyJob
Output:
As jobs may take a lot of time to complete, we are able to set a limit of the wait time. You can limit the wait time by using -Limit
parameter. The value that you set in -Limit
parameter is in seconds. When you will reach the time limit, the Receive-Job
will retrieve the current results at the moment even if the job has not been completed. It does not matter if you have received the results or if the time limit has been reached, the job will continue to run until it is completed.
[adinserter name=”In Article”]
Delete a background job
In order to delete a background job you need to use Remove-Job cmdlet. You can specify the job either by Id, Name, job variable.
Example 8
Code:
Start-Job -Name JobNetAdapter -ScriptBlock {Get-NetAdapter} Start-Job -Name JobDate -ScriptBlock {Get-Date} Get-Job Remove-Job -Name JobNetAdapter Get-Job
Output:
[adinserter name=”In Article”]
Investigation of failed jobs
Sometimes jobs may fail for various reason. If you want to find the reason of the failure, you need to use Reason sub-property of the job object. Lets see the below example to better understand.
Example 9
Code:
$SecurityLogsJob = Start-Job -Name SecurityLogs -ScriptBlock {Get-NetAdapters} Get-Job $SecurityLogsJob.ChildJobs[0].JobStateInfo.Reason
Output:
[adinserter name=”In Article”]
Child Jobs
When we are running background jobs, each job has one or more child jobs. If the job is started using Start-Job
or Invoke-Command -AsJob
, the parent job will not run any commands that are included in the script block. Child jobs will run the commands. The parent job has an executive role. This might not happen if you start a job using any other cmdlet. The child jobs are stored in the ChildJobs property of the parent job object. The ChildJobs property can contain one or many child job objects. The child job objects have a name, ID, and instance ID that differ from the parent job so that you can manage the parent and child jobs individually or as a unit.
If we want to get the parent job and the child jobs we need to use -IncludeChildJobs
parameter of Get-Job
cmdlet. If you want to get the child jobs only then you need to use Childjobs property of the job object. You are also able to select the Child jobs based on their state, by using -ChildJobState
parameter of Get-Job
cmdlet. Both -IncludeChildJobs and ChildJobState parameters have been introduced in Windows PowerShell 3.0.
Example 10
Code:
$SecurityLogsJob = Start-Job -Name SecurityLogs -ScriptBlock {Get-NetAdapters} Get-Job Get-Job -IncludeChildJob $SecurityLogsJob.ChildJobs Get-Job -Name Job2
Output:
The next explanation for the configuration of the child job is provided by Microsoft:
The configuration of the child job depends on the command that you use to start the job.
- When you use Start-Job to start a job on a local computer, the job consists of an executive parent job and a child job that runs the command.
- When you use the AsJob parameter of Invoke-Command to start a job on one or more computers, the job consists of an executive parent job and a child job for each job run on each computer.
- When you use Invoke-Command to run a Start-Job command on one or more remote computers, the result is the same as a local command run on each remote computer. The command returns a job object for each computer. The job object consists of an executive parent job and one child job that runs the command.
The parent job represents all of the child jobs. When you manage a parent job, you also manage the associated child jobs. For example, if you stop a parent job, all child jobs are stopped. If you get the results of a parent job, you get the results of all child jobs.
However, you can also manage child jobs individually. This is most useful when you want to investigate a problem with a job or get the results of only one of a number of child jobs started by using the AsJob parameter of Invoke-Command.
[adinserter name=”In Article”]
Remote Background Jobs
As we have mentioned above, you are not able not only to run job on local computers but also on remote computers. You are able to run jobs on remote computers by using any of the following methods.
- Start an interactive session with a remote computer, and start a job in the interactive session. The procedures are the same as running a local job, although all actions are performed on the remote computer.
- Run a background job on a remote computer that returns its results to the local computer. Use this method when you want to collect the results of background jobs and maintain them in a central location on the local computer.
- Run a background job on a remote computer that maintains its results on the remote computer. Use this method when the job data is more securely maintained on the originating computer.
By using the first and the third method, the results of the job will remain on the remote computer. In order to get the results and view them from the remote computer to local computer you need to save them in a file and read the content from the file.
Lets see below on how we are able to run background job using those methods.
Using Interactive session
Example 11
Code:
Enter-PSSession -ComputerName Remote-Computer $JobNetAdapter = Start-Job -Name JobNetAdapter -ScriptBlock {Get-NetAdapter} Get-Job -Name JobNetAdapter Receive-Job -Job $JobNetAdapter > C:\TestFolder\NetAdapter.txt Exit-PSSession $Session = New-PSSession -ComputerName Remote-Computer $ResultOnLocal = Invoke-Command -Session $Session -ScriptBlock {Get-Content -Path "C:\TestFolder\NetAdapter.txt"} Remove-PSSession -Session $Session $ResultOnLocal
Output:
Results to be returned on local computer
Example 12
Code:
Invoke-Command -ComputerName RemoteComputer -ScriptBlock {Get-NetAdapter} -AsJob $Result = Receive-Job -Name Job1 $Result
Output:
[adinserter name=”In Article”]
Results remain on remote computer
Example 13
Code:
$Session = New-PSSession -ComputerName RemoteComputer Invoke-Command -Session $Session -ScriptBlock {Start-Job -Name JobNetAdapter -ScriptBlock {Get-NetAdapter}} Invoke-Command -Session $Session -ScriptBlock {Get-Job -Name JobNetAdapter} $ResultOnLocal = Invoke-Command -Session $Session -ScriptBlock {Receive-Job -Name JobNetAdapter -Keep} $ResultOnLocal Invoke-Command -Session $Session -ScriptBlock {Receive-Job -Name JobNetAdapter > C:\TestFolder\NetAdapter.txt} $ResultOnLocal = Invoke-Command -Session $Session -ScriptBlock {Get-Content -Path "C:\TestFolder\NetAdapter.txt"} $ResultOnLocal
Output:
[adinserter name=”In Article”]
Job Types
PowerShell is able to run different types of jobs. You can use other types of job based on the task that you want to perform. From Windows PowerShell 3.0 and on, developers can write “job source adapters” that add new job types to PowerShell and include the job source adapters in modules. When you import the module, you can use the new job type in your session. For example, the PSScheduledJob module adds scheduled jobs and the PSWorkflow module adds workflow jobs.
Custom jobs types might differ significantly from standard Windows PowerShell background jobs. For example, scheduled jobs are saved on disk; they do not exist only in a particular session. Workflow jobs can be suspended and resumed. The cmdlets that you use to manage custom jobs depend on the job type. For some, you use the standard job cmdlets, such as Get-Job and Start-Job. Others come with specialized cmdlets that manage only a particular type of job. For detailed information about custom job types, see the help topics about the job type. To find the job type of a job, use the Get-Job cmdlet. Get-Job returns different job objects for different types of jobs. The value of the PSJobTypeName property of the job objects that Get-Job returns indicates the job type.
The above information has been taken from Microsoft. Below is the list of different job types that come with Windows PowerShell.
Job Types List
- BackgroundJob – Started by using the
Start-Job
cmdlet. - RemoteJob – Started by using the
-AsJob
parameter of theInvoke-Command
cmdlet. - PSWorkflowJob – Started by using the
-AsJob
parameter of a workflow. - PSScheduledJob – An instance of a scheduled job started by a job trigger.
- CIMJob – Started by using the
-AsJob
parameter of a cmdlet from a CDXML module. - WMIJob – Started by using the
-AsJob
parameter of a cmdlet from a WMI module. - PSEventJob – Created by running
Register-ObjectEvent
and specifying an action with the Action parameter.
I hope the tutorial about PowerShell Jobs is helpful.
Please let me know your comments and thoughts.
You feedback is appreciated.
[adinserter name=”In Article”]
Related Links
- PowerShell Tutorials
- PowerShell Scripts
- about_Jobs | Microsoft Docs
- about_Remote_Jobs | Microsoft Docs
- About Job Details – Microsoft Docs
- Start-Job – Microsoft Docs
- Get-Job – Microsoft Docs
- Receive-Job – Microsoft Docs
- Stop-Job – Microsoft Docs
- Wait-Job – Microsoft Docs
- Remove-Job – Microsoft Docs
- Invoke-Command – Microsoft Docs
- Get-NetAdapter – Microsoft Docs
- Get-Date – Microsoft Docs
- Get-Process – Microsoft Docs
- Get-ScheduledJob – Microsoft Docs
- New-JobTrigger – Microsoft Docs
- Register-ScheduledJob – Microsoft Docs
[adinserter name=”Matched-Content”]


Fav’d…
I have a start-job command, which kicks off OK and completes properly. However, i need it to wait until completion, after kicking off a certain number of jobs…That’s easy enough, if x == 100 etc then get-job | wait-job, right? Well when i run that, it actually returns the job completion for the 100 (or 10000) jobs i have running. I need it to wait minus the return of the job being Completed bit. I thought i had to put get-job | wait-job | receive-job to have it return info, but apparently not.
#just pseudo code mostly…
$count=0
$x = all my computers in a list
Foreach ($computer in $x)
{
$count++
if $count == 100 {get-job | wait-job}
start-job -name PingComputer -scriptblock {
param ($computer)
ping $computer
}
}
| Out-null is the winner…
No output:
get-job | wait-job | out-null
Will also work for start-job by itself…start-job …. | out-null