Scheduling Background Jobs in Windows PowerShell 3.0

Scheduling Background Jobs in Windows PowerShell 3.0

Rate This
  • Comments 11

One of the most common phone calls that the support team gets for Windows PowerShell is "How do I use Task Scheduler to schedule Windows PowerShell scripts?". As an administrator, you need to have full control over when scripts run in your environment. Perhaps you need run a script only during a one-off maintenance window or maybe you want to schedule some routine maintenance on a server so that it runs at non-peak times. Although it was possible to use Task Scheduler to invoke scripts in Windows PowerShell 2.0, it was not trivial. What's more, you were responsible for writing code to store the detailed results of your script if you wanted to view them later.

In Windows PowerShell 2.0, we introduced background jobs, which let you run commands asynchronously in the background. This allows you to get the prompt back and continue running commands at the command line while the background job runs. In keeping with our sacred vow to respect your investment in learning Windows PowerShell by reusing concepts, we reused jobs in many places with Windows PowerShell 3.0. This blog post introduces just one example of this: job scheduling. This feature allows administrators to schedule background jobs for execution at a later time or according to a particular schedule with a set of cmdlets right out of the box. One of the most valuable features of scheduled jobs in Windows PowerShell 3.0 is that we'll even take care of storing the results and output of your job.

Where to find the Job Scheduling cmdlets

The Job Scheduling cmdlets are delivered in the PSScheduledJob module that is included in Windows PowerShell 3.0 Beta and in the Windows Management Framework 3.0 Beta.

There are 16 cmdlets in the PSScheduledJob module that allow you to work with Scheduled Jobs, the triggers that cause them to run, and some more advanced configuration. To see the cmdlets, type:

PS > Get-Command -Module PSScheduledJob | Sort-Object Noun, Verb

Capability Name ModuleName
---------- ---- ----------
Cmdlet Add-JobTrigger psscheduledjob
Cmdlet Disable-JobTrigger psscheduledjob
Cmdlet Enable-JobTrigger psscheduledjob
Cmdlet Get-JobTrigger psscheduledjob
Cmdlet New-JobTrigger psscheduledjob
Cmdlet Remove-JobTrigger psscheduledjob
Cmdlet Set-JobTrigger psscheduledjob
Cmdlet Disable-ScheduledJob psscheduledjob
Cmdlet Enable-ScheduledJob psscheduledjob
Cmdlet Get-ScheduledJob psscheduledjob
Cmdlet Register-ScheduledJob psscheduledjob
Cmdlet Set-ScheduledJob psscheduledjob
Cmdlet Unregister-ScheduledJob psscheduledjob
Cmdlet Get-ScheduledJobOption psscheduledjob
Cmdlet New-ScheduledJobOption psscheduledjob
Cmdlet Set-ScheduledJobOption psscheduledjob

 

Basics of the Job Scheduling Cmdlets:

The JobTrigger cmdlets let you determine when scheduled jobs actually run. You can schedule jobs to execute one time (now or at a later date), daily, weekly, when certain users log on, or when the system first boots up.

The ScheduledJob cmdlets allow you to create and configure scheduled jobs. You use these cmdlets to perform actions like registering, unregistering, enabling and disabling scheduled jobs on the computer.

The ScheduledJobOption cmdlets allow you to specify advanced settings for scheduled jobs. With these cmdlets, you can configure many of the settings you're already familiar with in Task Scheduler, such as idle conditions that must be met before the job starts. The default values for each scheduled job should be sufficient in most cases, but the flexibility is there.

 

An example:

Imagine that you are incredibly passionate about configuring your computers for optimal energy efficiency. You've written a few lines to take the output of Powercfg.exe /energy and extract only the items that represent the most severe infractions. You want to run this analysis every night for a certain period of time so you can understand which issues appear most frequently.

With just a few lines, we can schedule our script to run on the server every night as part of an "EnergyAnalysisJob".

PS > $trigger = New-JobTrigger -Daily -At 3am
PS > Register-ScheduledJob -Name EnergyAnalysisJob -Trigger $trigger -ScriptBlock
{
powercfg.exe -energy -xml -output C:\temp\energy.xml -duration 60 | Out-Null
$EnergyReport = [xml](get-content C:\temp\energy.xml)
$namespace = @{ ns = "http://schemas.microsoft.com/energy/2007" }
$xPath = "//ns:EnergyReport/ns:Troubleshooter/ns:AnalysisLog/ns:LogEntry[ns:Severity = 'Error']"
$EnergyErrors = $EnergyReport | Select-Xml -XPath $xPath -Namespace $namespace
$EnergyErrors.Node | select Name, Description
}

 

Id Name JobTriggers Command Enabled
-- ---- ----------- ------- -------
1 EnergyAnalys... {1} ... True

 

If you've ever used the Start-Job cmdlet, the syntax of Register-ScheduledJob will look very familiar to you.

You can view the jobs that you have scheduled at any time by using the Get-ScheduledJob cmdlet. Scheduled Jobs are stored on a per-user basis, so Get-Scheduled job will only show the scheduled jobs that are relevant to you.

Windows PowerShell 3.0 keeps track of the results and output of scheduled jobs for you. If you come back to the server that runs the scheduled job a couple of days later, you can use the Job cmdlets (the same ones that you use to manage background jobs) to view and get the results of the EnergyAnalysisJob scheduled job. The nice thing about scheduled job results is that they are available even in different sessions! Since you are not always around to receive results when a scheduled job runs, we store them on disk so you can receive them at any time.

Here's an important "gotcha" that you should know. To get the results of scheduled jobs, you must import the PSScheduledJob module into the current session (Import-Module PSScheduledJob). Otherwise, the Job cmdlets, such as Get-Job and Receive-Job, do not return results for scheduled jobs. This is a bit of an exception to the module auto-loading behavior in Windows PowerShell 3.0. The reason is that Get-Job is in the Microsoft.PowerShell.Core snap-in, so using it doesn't automatically import the PSScheduledJob module. Also, if Get-Job were to automatically import all of the modules that implement custom job types, over time, the output would be crowded with irrelevant job types and performance might be affected by importing dozens of modules that aren't needed.

PS > Import-Module PSScheduledJob

 

With the PSScheduledJob module imported, Get-Job shows the results of "instances" of our scheduled jobs.

PS > Get-Job

Id Name State HasMoreData Location Command
-- ---- ----- ----------- -------- -------
2 EventCollect... Completed True localhost ...
4 EnergyAnalys... Completed True localhost ...
6 EnergyAnalys... Completed True localhost ...

 

Scheduled jobs have BeginTime and EndTime properties that tell when the job instance actually ran.

PS > Get-Job EnergyAnalysis | Select-Object Name,BeginTime,EndTime

Name BeginTime EndTime
---- ----------- ---------
EnergyAnalysisJob 3/12/2012 3:00:01 AM 3/12/2012 3:01:12 AM
EnergyAnalysisJob 3/13/2012 3:00:01 AM 3/13/2012 3:01:14 AM

 

To get the results of a scheduled job instance, use the Receive-Job cmdlet.

PS > Receive-Job -Name EnergyAnalysisJob

# Results will vary based on your system's configuration, but you will see records like:
Name : USB Device not Entering Selective Suspend
Description : This device did not enter the USB Selective Suspend state. Processor power management may be prevented when this USB device is not in the Selective Suspend state. Note that this issue will not prevent the system from sleeping.

 

By default, Windows PowerShell keeps the results of the last 32 instances of each scheduled job. After 32 results are stored for a particular scheduled job, the oldest ones are overwritten by subsequent executions. To change the number of results saved for each scheduled job, use the MaxResultCount parameter of the Set-ScheduledJob cmdlet.

PS > Get-ScheduledJob -Name EnergyAnalysisJob | Set-ScheduledJob -MaxResultCount 100

 

Lastly, if you want to start a scheduled job manually rather than waiting for its triggers, you can use the DefinitionName parameter of the Start-Job cmdlet.

PS > Start-Job -DefinitionName EnergyAnalysisJob

 

As you can see, working with scheduled jobs in Windows PowerShell 3.0 is a lot like working with regular background jobs, but with much more control. We hope you enjoy the flexibility and simplicity of this cool new feature.

 

Travis Jones [MSFT]
Program Manager - Windows PowerShell
Microsoft Corporation

Leave a Comment
  • Please add 6 and 4 and type the answer here:
  • Post
  • Any chance of being able to use PowerShell eventing as a job trigger?

  • Thanks , Going to have to give this a try.

  • Hi Josheinstein -

    For this release we're going to be limited to the handful of triggers offered from the Task Scheduler engine. If you want to file the PowerShell eventing suggestion on Connect (connect.microsoft.com/powershell), other folks from the community will be able to vote on it and we will certainly keep track of it.

    Thanks!

  • For help about Scheduled Jobs in Windows PowerShell 3.0, see technet.microsoft.com/.../hh847863.aspx.

  • I don't like the fact that if you don't import the PSScheduleJobs module, the results of scheduled jobs will not be saved. Imagine how many support calls this little detail will generate? Please make it sot that if the scheduled jobs commandlets are used to schedule a job are used then to automaically import the module.

  • So, are you creating a new Task Scheduler or will jobs that are created with these cmdlets show up in the regular Windows Task Scheduler under Computer Management?

    Thanks!

  • Hello Anon -

    The results of scheduled jobs will always be saved, regardless of which modules are imported. Their results will only be returned from calls to Get-Job if the PSScheduledJob module is imported. I'm not sure if that changes your feedback any.

    Thanks

  • Hello Jim -

    Jobs created with these cmdlets will show up in the regular Windows Task Scheduler under: Task Scheduler Library\Microsoft\Windows\PowerShell\ScheduledJobs

    Thanks!

  • Very nice.

  • Hi, thanks for sharing, this is great!

    To get BeginTime and EndTime I have to use different object names, such as PSBeginTime and PSEndTime >>> Get-Job EnergyAnalysis | Select-Object Name,PSBeginTime,PSEndTime

  • Good Information

Page 1 of 1 (11 items)