Summary: Microsoft Scripting Guy, Ed Wilson, continues his discussion about Windows PowerShell scheduled jobs.

Microsoft Scripting Guy, Ed Wilson, is here. Last night was the Expo floor meet-and-greet at TechEd in Houston. It was a crazy time, and we had literally thousands of people stopping by to say "hi," and to meet up with other Windows PowerShell peeps. It was an awesome opportunity to hang out with so many people who are interested in using Windows PowerShell. The cool thing is that many people had already read yesterday’s post about Windows PowerShell scheduled jobs, and several had questions. So I dashed back to my hotel room last night and went to work on today’s post.

Note  This is the second in a series of posts about the Windows PowerShell scheduled jobs feature. You should read the first post, Introduction to PowerShell Scheduled Jobs, before you read today’s post.

Yesterday I created a Windows PowerShell scheduled job with a time trigger, and it ran successfully. Then, I shut down my laptop. Now, we are back at the hotel, I power up my laptop, and guess what? When I use the Get-ScheduledJob cmdlet, I see that the Windows PowerShell scheduled jobs still exist. They are shown here:

Image of command output

Note  To use any of the *job cmdlets (for example, Get-Job or Receive-Job), the PSScheduledJob module must load into the current session. This happens when you use a cmdlet such as Get-ScheduledJob. You can also specifically import the module by using Import-Module PSScheduledJob.

I can also check to see if the job completed and if there is any data left. To do this, I use the Get-Job cmdlet. I can then use the name or the job ID. The easiest thing to do is to give the job a decent name, and use the name. This is because the job ID from Get-ScheduledJob and the job ID from Get-Job are different numbers. When I get the job, I pipe it to the Format-List cmdlet as shown here:

Image of command output

One thing that I like to do is see how long the scheduled job takes to run. This is useful to help to develop some sort of a track record for comparison. I can use the New-TimeSpan cmdlet and select the PSBeginTime and the PSEndTime properties to obtain this information. Here is the command I use:

New-TimeSpan -Start (get-job -name gps).psbegintime -End (get-job -name gps).psendtime

The command returns a TimeSpan object. I generally simply return the entire object because, at times, I do not know how long the job runs. Pay really close attention when reading the object because the first portion contains the number of days, hours, minutes, seconds, and milliseconds the job takes to complete. I have to add these parts together to get a total time. Or I can go to the Total* section. For example, this job took a total of 2.2812358 seconds.

Days              : 0

Hours             : 0

Minutes           : 0

Seconds           : 2

Milliseconds      : 281

Ticks             : 22812358

TotalDays         : 2.64031921296296E-05

TotalHours        : 0.000633676611111111

TotalMinutes      : 0.0380205966666667

TotalSeconds      : 2.2812358

TotalMilliseconds : 2281.2358

Even though I rebooted my computer, I can still look at the job results. This is because I used the –Keep parameter when viewing the results. This is shown here:

Image of command output

One of the cool things I can do is run the job directly. This is useful, for example, when I have a scheduled job that was set up to run on a schedule, and I want an impromptu run. A classic illustration of this situation is when I have a scheduled backup that runs each morning, but I have made a significant number of changes to a system (or I am getting ready to make a significant number of changes), and I would like to run an impromptu backup without modifying my regularly scheduled backup.

To run a scheduled job as a one-off, all I need to do is to use the Start-Job cmdlet and specify the name of the job as shown here:

PS C:\> Start-Job -DefinitionName gps

Id     Name            PSJobTypeName   State         HasMoreData     Location

--     ----            -------------   -----         -----------     --------

5      GPS             PSScheduledJob  Running       True            localhost

Deleting stuff

To remove job triggers, I can use the Remove-JobTrigger cmdlet. One way to do this is to remove the job trigger by the name of the trigger itself. To find this, I can use the Get-ScheduledJob cmdlet and pipe the results to Get-JobTrigger. I can also use the ID of the trigger, or I can pipe a scheduled job definition object to the cmdlet. Here are a couple of examples:

Remove-JobTrigger -Id 1

Get-ScheduledJob | Get-JobTrigger

Keep in mind that the input object is a ScheduledJobDefinition object that comes from Get-ScheduledJob, and not a ScheduledJobTrigger object. Therefore, the following command fails:

Image of error message

To delete Windows PowerShell scheduled jobs, you use the Unregister-ScheduledJob cmdlet.

Note  It is a bit confusing that the PSScheduledJob module uses Register-ScheduledJob and Unregister-ScheduledJob instead of the New and Remove verbs. But with scheduled jobs, you are actually registering and unregistering, so the verbs make sense from a technical perspective.

If I want to delete all of my Windows PowerShell scheduled jobs, I use the following command:

Get-ScheduledJob | Unregister-ScheduledJob

There you have more info about using Windows PowerShell scheduled jobs. Scheduled Jobs 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, or post your questions on the Official Scripting Guys Forum. See you tomorrow. Until then, peace.

Ed Wilson, Microsoft Scripting Guy