Last Update: Sep 04, 2024 | Published: May 21, 2015
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.
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.
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.
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. 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. I will create a job option object to require network access.
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. As you can see, I have two jobs, but where are they in Task Scheduler? You have to drill down: MicrosoftWindowsPowershellScheduled Jobs. 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. 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. It completed without error. What did I get? How about that! It worked. 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. 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:scriptsGet-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. 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. 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. 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.