Summary: Microsoft Scripting Guy, Ed Wilson, introduces the Windows PowerShell scheduled job feature.
Microsoft Scripting Guy, Ed Wilson, is here. In all the hubbub about all the great features introduced in Windows PowerShell 3.0, one (actually more than one) feature was somewhat overlooked. With Windows PowerShell 3.0 bringing features such as workflow, PowerShell Web Access, support for disconnected sessions, CIM cmdlets, updatable Help, module auto loading, and improved Windows PowerShell ISE, it was really understandable that the scheduled job feature was simply overlooked by nearly everyone. This is not because the feature is bad—it is just that all the other way cool stuff left little room on the plate of the average IT pro.
Note I have written quite a bit about scheduled tasks and Windows PowerShell over the years. I have written about the classic scheduled tasks and the newer task scheduler. For more information, see this collection of blog posts.
It’s a job, it’s a scheduled task…
Windows PowerShell scheduled jobs rely on the background jobs feature that was introduced in Windows PowerShell 2.0. But unlike a plain old background job, Windows PowerShell 3.0 added the ability to schedule the background job. This makes Windows PowerShell scheduled jobs like a cross between a Windows PowerShell background job and Task Scheduler tasks.
Because Windows PowerShell scheduled jobs are, at their very heart, background jobs, it means that they run asynchronously in the background. It also means that I can use the *job cmdlets to manage Windows PowerShell scheduled jobs. Thereby, I protect my investment in learning Windows PowerShell in the first place. Start-Job, Get-Job, Stop-Job, and Receive-Job can be used to manage the Windows PowerShell scheduled jobs.
In addition to the generic *job cmdlets, Windows PowerShell 3.0 introduces a PSScheduledJob module that contains the following 16 cmdlets:
PS C:\> Get-Command -Module PSScheduledJob | sort verb
CommandType Name ModuleName
----------- ---- ----------
Cmdlet Add-JobTrigger PSScheduledJob
Cmdlet Disable-ScheduledJob PSScheduledJob
Cmdlet Disable-JobTrigger PSScheduledJob
Cmdlet Enable-ScheduledJob PSScheduledJob
Cmdlet Enable-JobTrigger PSScheduledJob
Cmdlet Get-ScheduledJobOption PSScheduledJob
Cmdlet Get-ScheduledJob PSScheduledJob
Cmdlet Get-JobTrigger PSScheduledJob
Cmdlet New-ScheduledJobOption PSScheduledJob
Cmdlet New-JobTrigger PSScheduledJob
Cmdlet Register-ScheduledJob PSScheduledJob
Cmdlet Remove-JobTrigger PSScheduledJob
Cmdlet Set-ScheduledJobOption PSScheduledJob
Cmdlet Set-ScheduledJob PSScheduledJob
Cmdlet Set-JobTrigger PSScheduledJob
Cmdlet Unregister-ScheduledJob PSScheduledJob
So, how does it work (or step-by-step)
Using the Windows PowerShell scheduled job cmdlets to create a scheduled job involves the following steps:
- Decide when to run the scheduled job.
- Decide how often to run the scheduled job.
- Decide what command to run.
- Create and configure the scheduled job.
Note To create and schedule a Windows PowerShell scheduled job requires elevated permissions.
I create a trigger, but when I try to register the scheduled job, if I have not opened Windows PowerShell with admin rights, the following error message appears:
To launch with admin rights, right-click the Windows PowerShell icon and click Run as Administrator. The menu is shown in the following image:
After I open the Windows PowerShell console with admin rights, I create the trigger, and I register the scheduled job. The script to do this is:
$trigger = New-JobTrigger -Once -At 13:45
Register-ScheduledJob -Name GPS -Trigger $trigger -ScriptBlock {GPS}
This time, the command returns a ScheduledJobDefinition object. This object contains the name of the scheduled job, the job trigger, job ID, and the command itself. The command and the returned object are shown in the following image:
I can now use the Get-ScheduledJob cmdlet to check the status of the scheduled job as shown here:
PS C:\> Get-ScheduledJob -Id 1
Id Name JobTriggers Command Enabled
-- ---- ----------- ------- -----
1 GPS 1 GPS True
If I want to see what job options were used when creating the scheduled job, I use the Get-ScheduledJobOption cmdlet. This command and associated output are shown here:
PS C:\> Get-ScheduledJobOption -Id 1
StartIfOnBatteries : False
StopIfGoingOnBatteries : True
WakeToRun : False
StartIfNotIdle : True
StopIfGoingOffIdle : False
RestartOnIdleResume : False
IdleDuration : 00:10:00
IdleTimeout : 01:00:00
ShowInTaskScheduler : True
RunElevated : False
RunWithoutNetwork : True
DoNotAllowDemandStart : False
MultipleInstancePolicy : IgnoreNew
JobDefinition : Microsoft.PowerShell.ScheduledJob.ScheduledJobDefinition
If I want to see what trigger was used for the scheduled job, I first get the scheduled job, and then I pipe it to the Get-JobTrigger cmdlet. This command is shown here:
PS C:\> Get-ScheduledJob -Id 1 | Get-JobTrigger
Id Frequency Time DaysOfWeek Enabled
-- --------- ---- ---------- -------
1 Once 5/8/2014 1:45:00 PM True
To see if the job ran, I use the Get-Job cmdlet as shown here:
PS C:\> get-job
Id Name PSJobTypeName State HasMoreData Location
-- ---- ------------- ----- ----------- --------
2 GPS PSScheduledJob Completed True localhost
3 GPS1 PSScheduledJob Completed True localhost
I see there are two jobs that completed. So I look at the first job. Notice that this number is a different ID number than the one I received from Get-ScheduledJob:
PS C:\> get-job -Id 2
Id Name PSJobTypeName State HasMoreData Location
-- ---- ------------- ----- ----------- --------
2 GPS PSScheduledJob Completed True localhost
To receive the results of the job, I use the Receive-Job cmdlet. To keep the results, I use the –Keep parameter. This will enable me to look at the results a second time. If I do not use the –Keep parameter, I will not be able to see the results a second time (unless I store the results in a variable or some other mechanism).
Receive-Job -Id 2 -Keep
The command and the output from the command are shown here:
That is all there is to playing around with Windows PowerShell scheduled jobs. Scheduled Job Week will continue tomorrow when I will talk about more cool stuff.
I invite you to follow me on Twitter and Facebook. If you have any questions, send email to me at scripter@microsoft.com, or post your questions on the Official Scripting Guys Forum. See you tomorrow. Until then, peace.
Ed Wilson, Microsoft Scripting Guy