Coming Soon: GET-IT: Endpoint Management 1-Day Conference on September 28th at 9:30 AM ET Coming Soon: GET-IT: Endpoint Management 1-Day Conference on September 28th at 9:30 AM ET
PowerShell

Optimizing PowerShell Scheduled Jobs

In the first part of this series I demonstrated how to create a simple PowerShell scheduled job, where you can take your existing PowerShell scripts and easily run them as scheduled tasks. Today, I want to give you a little more information on what’s happening behind the scenes.

Here are the scheduled jobs that I’ve set up.

The get-scheduledjob cmdlet in Windows PowerShell. (Image Credit: Jeff Hicks)
The get-scheduledjob cmdlet in Windows PowerShell. (Image Credit: Jeff Hicks)

In my previous article, I set up the first job. Let’s look at it from PowerShell’s perspective in more detail.

The scheduled job execution details in Windows PowerShell. (Image Credit: Jeff Hicks)
The scheduled job execution details in Windows PowerShell. (Image Credit: Jeff Hicks)

I’ve highlighted the execution details. The scheduled task is launching PowerShell.exe and running a complicated command. You can see the same thing in the Task Scheduler.

Sponsored Content

Say Goodbye to Traditional PC Lifecycle Management

Traditional IT tools, including Microsoft SCCM, Ghost Solution Suite, and KACE, often require considerable custom configurations by T3 technicians (an expensive and often elusive IT resource) to enable management of a hybrid onsite + remote workforce. In many cases, even with the best resources, organizations are finding that these on-premise tools simply cannot support remote endpoints consistently and reliably due to infrastructure limitations.

Task Scheduler. (Image Credit: Jeff Hicks)
Task Scheduler. (Image Credit: Jeff Hicks)

Here’s how the magic happens. When you create a PowerShell scheduled job, it has to be persisted to disk so that the Task Scheduler knows what to execute. The files for each job are stored under $env:LocalAppData\Microsoft\Windows\PowerShell\ScheduledJobs.

The file path for stored scheduled jobs. (Image Credit: Jeff Hicks)
The file path for stored scheduled jobs. (Image Credit: Jeff Hicks)

There is a directory for each scheduled job. Within each directory is an XML file with the job definition and the results.

Within each directory for a scheduled job, there's an associated XML file. (Image Credit: Jeff Hicks)
Within each directory for a scheduled job, there’s an associated XML file. (Image Credit: Jeff Hicks)

Don’t bother trying to parse the XML file. You can grab everything you need from this file with the scheduled job cmdlets. Because the output is also persisted to disk, you can always get the job results.

Again, you don’t need to be concerned about parsing these results. Instead use the job cmdlets.

Using the receive-job PowerShell cmdlet. (Image Credit: Jeff Hicks)
Using the receive-job PowerShell cmdlet. (Image Credit: Jeff Hicks)

I modified my original script to get the report file, but there’s one caveat. If you want to see these type of job results in PowerShell 3.0, you need to first import the PSScheduledJob module. In PowerShell 4.0, this module is imported automatically. You should get results every time the job runs regardless of whether you scheduled the task to run automatically or manually ran the task from PowerShell or the Task Scheduler.

The job results will persist between PowerShell sessions and overtime this can clutter your job listings. When you register a scheduled job, it will retain the 32 most recent results by default. That’s what my current job is doing. Look at second figure again and notice the ExecutionHistoryLength parameter. I’m going to change the current job to only keep the five most recent results.

get-scheduledjob "dc service report" | Set-ScheduledJob -MaxResultCount 5

If you know in advance how many results to retain, Register-ScheduledJob also has a MaxResultCount property. Otherwise, you can manually delete job results like any other job.

get-job -Name "DC Service Report" | Remove-Job

If you unregister a job, this will not only remove it from the Task Scheduler, but it will also delete all the associated files, which means you will lose any job results. If you need to, you can easily disable a job so that it won’t remove anything.

The Disable-ScheduledJob cmdlet. (Image Credit: Jeff Hicks)
The Disable-ScheduledJob cmdlet. (Image Credit: Jeff Hicks)

When you are ready to resume, use Enable-ScheduledJob.

The scheduled job cmdlets aren’t perfect. You may find that you need to tweak the scheduled task itself. To start, let’s say I want to adjust my current job trigger.

The get-jobtrigger cmdlet in Windows PowerShell. (Image Credit: Jeff Hicks)
The get-jobtrigger cmdlet in Windows PowerShell. (Image Credit: Jeff Hicks)

Perhaps I only need this to run Monday through Friday.

get-jobtrigger -Name "DC Service Report" | Set-JobTrigger -Weekly -DaysOfWeek "Monday","Tuesday","Wednesday","Thursday","Friday"

As you can see, this changed the scheduled task.

Our scheduled task has been updated. (Image Credit: Jeff Hicks)
Our scheduled task has been updated. (Image Credit: Jeff Hicks)

Be careful though because when you change trigger types, I went from daily to weekly, it changes the job. Now when I run the job I get access denied because I lost the credential.

get-scheduledjob "DC Service Report" | Set-ScheduledJob -Credential globomantics\jeff

Ideally, you want to get everything right the first time when you create the scheduled job. But let’s say I want to run this when I log on to my computer and then once again every hour. If you look at help for New-JobTrigger, there is no parameter set that will let me do that. I will have to manually change it in the Task Scheduler.

Editing the trigger in Task Scheduler. (Image Credit: Jeff Hicks)
Editing the trigger in Task Scheduler. (Image Credit: Jeff Hicks)

PowerShell can’t see the repetition information when it comes to the scheduled job.

I think for the majority of you this shouldn’t be a problem, but I wanted you to be aware. And there is one more gotcha with scheduled jobs. I have another scheduled job set up.

But the job never works.

Our job has failed to run. (Image Credit: Jeff Hicks)
Our job has failed to run. (Image Credit: Jeff Hicks)

Looking at the job in Task Scheduler tells me that the “last run of the task was terminated by the user (0x41306).” Turns out there is an odd bug when creating a weekly job using alternate credentials, which has been reported to Microsoft.

When I created the job, I was logged on as Globomantics\Jeff, but I configured the job to use Globomantics\Administrator. If I change the job credential to my Jeff account, it appears to work. The bottom line is that you will need to carefully test all of this in a non-production environment.

I see PowerShell scheduled jobs as the reward for learning PowerShell in the first place. You should be able to automate the routine, the mundane and the boring right out of your day. If you are using scheduled jobs, I’d love to hear what problems they are solving.

Related Topics:

BECOME A PETRI MEMBER:

Don't have a login but want to join the conversation? Sign up for a Petri Account

Register
Comments (0)

Leave a Reply

Live Webinar: Active Directory Security: What Needs Immediate Priority!Live on Tuesday, October 12th at 1 PM ET

Attacks on Active Directory are at an all-time high. Companies that are not taking heed are being punished, both monetarily and with loss of production.

In this webinar, you will learn:

  • How to prioritize vulnerability management
  • What attackers are leveraging to breach organizations
  • Where Active Directory security needs immediate attention
  • Overall strategy to secure your environment and keep it secured

Sponsored by: