Creating PowerShell Scheduled Jobs With The New-JobTrigger Cmdlet

PowerShell scheduled jobs is a feature that I don’t think gets as much attention as it should. Although this feature has a few quirks, I think it improves productivity for a wide-majority of IT professionals. Because you’ve presumably invested time and resources in learning PowerShell, and perhaps you’ve started building useful library of tools, why not automate their execution?
As an example, you may have a daily task that runs each morning to check servers for errors in the system event log. If you were smart, you learned PowerShell and wrote a script to do the work. But why should you have to manually run the script every morning when you could set it to run as a scheduled task? That’s where PowerShell scheduled jobs come into play.

PowerShell Scheduled Job Benefits and Uses

A PowerShell scheduled job combines the benefits of using PowerShell with the ease of the task scheduler. If you’re running Windows 8 or later, don’t confuse the scheduled job cmdlets with the scheduled task cmdlets. They are completely separate and the latter requires Windows 8 or later. PowerShell scheduled jobs only requires PowerShell 3.0, so if you’re still on Windows 7, then you’re good to go. Let me show you how this all works.

Creating a PowerShell Scheduled Job

Although it’s possible to write a single PowerShell expression to set up a scheduled job, I’m going to break it down into steps. We first need a trigger. When do you want the job to execute? A benefit of a PowerShell scheduled job is that PowerShell does not need to be running. In fact, you may not even need to be logged in, since job execution is controlled by the task scheduler. To create a trigger, we will use the New-JobTrigger cmdlet.

The New-JobTrigger cmdlet in Windows PowerShell v3. (Image Credit: Jeff Hicks)
The New-JobTrigger cmdlet in Windows PowerShell v3. (Image Credit: Jeff Hicks)

For my example, I have something I want to run every day at 8:00 AM.

​
Next, I need to define what I'm going to run. I can specify a script file or a scriptblock. For this example, I want to use this scriptblock.
​
Get-Service $services -ComputerName chi-dc04,chi-dc01,chi-dc02 |
Sort Machinename |
Format-Table -GroupBy Machinename -property Name,Displayname,Status
}
​
It is very important that you verify your action, be it scriptblock or file works manually. In this case, I want a quick service check of my domain controllers.
A quick service check of domain controllers. (Image Credit: Jeff Hicks)
A quick service check of domain controllers. (Image Credit: Jeff Hicks)
The scheduled PowerShell job is going to run locally, but we'll first need network access. When you set up a scheduled task manually, then you may recall there's an option to ensure network access, among other options. We can do the same thing using the New-ScheduledJobOption cmdlet.
The New-ScheduledJobOption cmdlet in Windows PowerShell. (Image Credit: Jeff Hicks)
The New-ScheduledJobOption cmdlet in Windows PowerShell. (Image Credit: Jeff Hicks)
I will create a job option object to require network access.
The Register-ScheduledJob cmdlet in Windows PowerShell. (Image Credit: Jeff Hicks)
The Register-ScheduledJob cmdlet in Windows PowerShell. (Image Credit: Jeff Hicks)
With this information, I can build a hashtable of parameters and splat it to the cmdlet.
​
ScriptBlock = $action
Trigger = $trigger
ScheduledJobOption = $opt
}
Register-ScheduledJob @paramHash
​" width="523" height="269" /> Building our hashtable in Windows PowerShell. (Image Credit: Jeff Hicks)[/caption]
You can use Get-ScheduledJob to view jobs.
Viewing jobs with the Get-ScheduledJob cmdlet in Windows PowerShell. (Image Credit: Jeff Hicks)
Viewing jobs with the Get-ScheduledJob cmdlet in Windows PowerShell. (Image Credit: Jeff Hicks)
As you can see, I have two jobs, but where are they in Task Scheduler? You have to drill down: Microsoft\Windows\Powershell\Scheduled Jobs. 033015 1938 ScheduledPo7 By default, the scheduled job runs under your credentials. However, in looking at the task scheduler, there may be a problem since my job needs to access the network. Let's test so that I don't have to wait until 8:00 tomorrow morning to determine the issue. In PowerShell, I can manually start the job.
Manually running the job in Windows PowerShell. (Image Credit: Jeff Hicks)
Manually running the job in Windows PowerShell. (Image Credit: Jeff Hicks)
You'll notice that I use the regular Start-Job cmdlet but use a new parameter, DefinitionName. With this, I can manage and view the job like any other job. 033015 1938 ScheduledPo9 It completed without error. What did I get? 033015 1938 ScheduledPo10 How about that! It worked. 033015 1938 ScheduledPo11 It turns out my command, even though it is accessing the network, isn't requiring any network resources like access to a file share. In that case, I would need to store my password with the scheduled task. To demonstrate, let's get rid of this job with Unregister-Scheduledjob. 033015 1938 ScheduledPo12 Although you could delete the job in Task Scheduler, I recommend using the cmdlets because of the design behind scheduled jobs, which I'll discuss in detail in a future article. Because I'm going to revise my job, I might as well put it in a script as well. Using a scriptblock is handy for quick and dirty tasks. Should I ever need to revise the scriptblock, however, I have to touch the scheduled job. If I use a script file for the scheduled job, then I can update the script without touching the job.
​
Name = "DC Service Report"
FilePath = 'C:\scripts\Get-DCServiceReport.ps1'
Trigger = (New-Jobtrigger -Daily -At '8:00AM')
ScheduledJobOption = (New-ScheduledJobOption -RequireNetwork)
}
Register-ScheduledJob @paramHash
​
I'll go ahead and manually run this job.
Manually running the job again. (Image Credit: Jeff Hicks)
Manually running the job again. (Image Credit: Jeff Hicks)
The job completed without error, but I didn't receive a result. Let's stop for a moment and consider what I did. My script gets some service information and writes the results to a text file. The script writes nothing to the pipeline so naturally there is nothing in the job. The best I can do is check for the file. 033015 1938 ScheduledPo14 It still worked! But for the sake of discussion, let's say I want to store credentials with the job. I can specify a credential object during registration, or I can update the current job.
​
Refreshing the job in the task scheduler shows the change.
033015 1938 ScheduledPo15
I'm also going to revise the script so that the job result will have something to show me. Next time, we'll look at some aspects of working with PowerShell scheduled jobs.