Another new feature of PowerShell V2 is background jobs. These allow you to run commands asynchronously. In other words you can start a long running PowerShell job and immediately get control back. This allows you to keep working while the jobs is running. PowerShell supplies a number of new cmdlets to control these jobs.
Name
—-
Get-PSJob
Receive-PSJob
Remove-PSJob
Start-PSJob
Stop-PSJob
Wait-PSJob
Start-PSJob is used to create a new job. For these examples we will use get-service and get-process as examples.
PS> Start-PSJob -Command {get-service | sort status}
SessionId Name State HasMoreData Command
——— —- —– ———– ——-
1 Running True get-service | sort status
PS> Start-PSJob -Command {get-process | sort CPU}
SessionId Name State HasMoreData Command
——— —- —– ———– ——-
3 Running True get-process | sort CPU
You can view the status of jobs
PS> Get-PSJob
SessionId Name State HasMoreData Command
——— —- —– ———– ——-
1 Completed True get-service | sort status
3 Completed True get-process | sort CPU
if you are going to have a lot of jobs running it will be easier to keep track of them by assigning names or using variables to hold the job objects. As I have done either in this case I will need to use Receive-PSJob and Get-PSJob together to see the results
PS> Receive-PSJob -Job ( Get-PSJob -SessionId 1)
Status Name DisplayName
—— —- ———–
Stopped MSIServer Windows Installer
Stopped MSDTC Distributed Transaction Coordinator
Stopped mnmsrvc NetMeeting Remote Desktop Sharing
Stopped NetTcpPortSharing Net.Tcp Port Sharing Service
Stopped NetDDEdsdm Network DDE DSDM
Stopped NetDDE Network DDE
Stopped ImapiService IMAPI CD-Burning COM Service
etc
Even though the data has been received the job still shows in the list if Get-PSJob is used. To remove the job you use
PS> Remove-PSJob -Job ( Get-PSJob -SessionId 1)
PS> Get-PSJob
SessionId Name State HasMoreData Command
——— —- —– ———– ——-
3 Completed True get-process | sort CPU
Wait-PSJob suppresses the command prompt until the job has finished and Stop-PSJob cause the job to cease.
If we create a simple script file – test3.ps1 containing
Get-Process | Select-Object Name
we can run it as
$job = Start-PSJob -Command "C:scriptstest3.ps1"
and get the results by
PS> Receive-PSJob $job
Name PSIPHostEntry RunspaceID Pipeline
—- ————- ———- ——–
alg xpn 70bcf494-6b26-41ab-b1fb-a1… C:scriptstest3.ps1
csrss xpn 70bcf494-6b26-41ab-b1fb-a1… C:scriptstest3.ps1
ctfmon xpn 70bcf494-6b26-41ab-b1fb-a1… C:scriptstest3.ps1
explorer xpn 70bcf494-6b26-41ab-b1fb-a1… C:scriptstest3.ps1
hh xpn 70bcf494-6b26-41ab-b1fb-a1… C:scriptstest3.ps1
Idle xpn 70bcf494-6b26-41ab-b1fb-a1… C:scriptstest3.ps1
lsass xpn 70bcf494-6b26-41ab-b1fb-a1… C:scriptstest3.ps1
powershell xpn 70bcf494-6b26-41ab-b1fb-a1… C:scriptstest3.ps1
powershell xpn 70bcf494-6b26-41ab-b1fb-a1… C:scriptstest3.ps1
PowerShell Assistant xpn 70bcf494-6b26-41ab-b1fb-a1… C:scriptstest3.ps1
etc
It is possible to restrict what is viewed on return
PS> Receive-PSJob $job | select name
Name
—-
alg
csrss
ctfmon
explorer
hh
Idle
lsass
powershell
powershell
PowerShell Assistant
etc
It is also possible to run jobs against one or more remote machines
$job = Start-PSJob -ComputerName dc02 -Command {get-process | sort CPU}
The output is retrieved by Receive-PSJob as previously
In many respects this is a better option for running PowerShell against remote machines as the job can be left running in the background while other tasks are performed – it even gives time for a quick game of PowerShell Space Invaders!!