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.

– Starts a background job on a local computer. Get-Job – Gets the background jobs that were started in the current session.

– Gets the background jobs that were started in the current session. Receive-Job – Gets the results of background jobs.

– Gets the results of background jobs. Stop-Job – Stops a background job.

– Stops a background job. Wait-Job – Suppresses the command prompt until one or all jobs are complete.

– Suppresses the command prompt until one or all jobs are complete. Remove-Job – Deletes a background job.

– Deletes a background job. Invoke-Command – The AsJob parameter runs any command as a background job on a remote computer. You can also use Invoke-Command to run any job command remotely, including a Start-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.

cmdlet. RemoteJob – Started by using the -AsJob parameter of the Invoke-Command cmdlet.

parameter of the cmdlet. PSWorkflowJob – Started by using the -AsJob parameter of a workflow.

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.

parameter of a cmdlet from a CDXML module. WMIJob – Started by using the -AsJob parameter of a cmdlet from a WMI module.

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

[adinserter name=”Matched-Content”]