Working with scheduled tasks from Windows PowerShell

Traditionally Windows administrators is used to work with the Windows Task Scheduler using the command line utilities at.exe and schtasks.exe. Schtasks.exe was introduced as a replacement for at.exe in Windows XP/Windows Server 2003, while at.exe still exists in the latest Windows versions for backwards compatibility.

Both of the utilities works in Windows PowerShell, but they both produce text, not objects. This means we can not use for example the object manipulation cmdlets Where-Object and Select-Object on the output from these utilities. There are some tricks you can use to get the output from external applications in PowerShell into objects. An example on this is the /fo parameter on schtasks.exe, which allow us to specify the format of the output from the command. Since PowerShell has a ConvertFrom-Csv cmdlet, this means we can do this to get all scheduled tasks in object form:

schtasks.exe /query /fo csv | ConvertFrom-Csv

This allows us to use for example the Where-Object cmdlet to filter the output based on the Status-property:

image

To make this utilities behave more PowerShell friendly we could create custom functions which for example wraps schtasks.exe /create in a New-Task function, but still it would require a lot of work to parse the text output into custom objects.

Task Scheduler 2.0 which was released in Windows Vista and Windows Server 2008 introduced a COM-interface. This makes possible to access the Task Scheduler interface using PowerShell: New-Object -ComObject Schedule.Service

By using this COM-object we can access the Task Scheduler Scripting Objects, which produces objects rather than text. Of course this still requires a bit of work and the need to read quite a bit of documentation in order to make it user friendly for an administrator. Luckily the PowerShell team released a TaskScheduler module which builds on this COM-object as part of the PowerShell Pack, released as part of the Windows 7 Resource Kit.

When you have installed the MSI-file from the PowerShell Pack download page, you can import the TaskScheduler module and have a look at the available functions:

image

We can for example use the Get-ScheduledTask function to retrieve all scheduled tasks on the local computer:

image

This is an example of how to schedule a PowerShell script to run every day at 06.00:

# Import the module
Import-Module TaskScheduler

# Create a new task
$task = New-Task
$task.Settings.Hidden = $true

# Add an action and a trigger
Add-TaskAction -Task $task -Path C:Windowssystem32WindowsPowerShellv1.0powershell.exe -Arguments "-File C:MyScript.ps1"
Add-TaskTrigger -Task $task -Daily -At "06:00"

# Register the task
Register-ScheduledTask -Name "PowerShell - MyScript.ps1" -Task $task

When the above example is run we can find the new scheduled task in the Task Scheduler:

image

image

image

image

Or of course by using the Get-ScheduledTask function:

image

Instead of configuring a script file (ps1-file) to be the task action, we could have specified a script block to the Add-TaskAction function:

Add-TaskAction -Task $task -Script {“Hello World”}

Then the script block would be passed as an encoded command to powershell.exe:

-encodedCommand IgBIAGUAbABsAG8AIABXAG8AcgBsAGQAIgA=

An advantage of this approach is that we do not need to save our code to disk in advance to configuring it as a scheduled task.

Scheduled jobs in PowerShell 3.0

With the new version of Windows coming out later this year, we will also get a new version of Windows PowerShell. One of the new features in PowerShell 3.0 is a new module called PSScheduledJobs, which allows us to schedule jobs natively from within PowerShell. In addition, the output and results from the job is actually stored so that we can retrieve them after the job is executed, just like we could with background jobs in PowerShell 2.0.

The following information and examples is based on the Windows PowerShell 3.0 version available in the Windows 8 Consumer Preview.

Here we can see the cmdlets available in the PSScheduledJob module:

image

The following example is using the PSScheduledJob module to do the same as the previous example which used the TaskScheduler module from the PowerShell Pack:

# Import the module (not necessary due to the new module autoloading in PowerShell 3.0)
Import-Module PSScheduledJob

# Add a job option
$joboption = New-ScheduledJobOption -HideInTaskScheduler

# Add a trigger
$trigger = New-JobTrigger -Daily -At "06:00"

# Register the job
Register-ScheduledJob -Name "PowerShell - MyScript.ps1" -Trigger $trigger -FilePath C:MyScript.ps1 -ScheduledJobOption $joboption

If we want to specify a script block instead of a script file, we can use the ScriptBlock parameter instead of the FilePath parameter of Register-ScheduledJob:

Register-ScheduledJob -Name “PowerShell – MyScript.ps1″ -Trigger $trigger -ScriptBlock {“Hello World”}

If we look at the new task that is created from the example above we can see the following:

image

The arguments passed to powershell.exe:

-NoLogo -NonInteractive -WindowStyle Hidden -Command “Import-Module PSScheduledJob; $jobDef = [Microsoft.PowerShell.ScheduledJob.ScheduledJobDefinition]::LoadFromStore(‘PowerShell – MyScript.ps1′, ‘C:Users<username>AppDataLocalWindowsPowerShellScheduledJobs’); $jobDef.Run()”

We can see that the job is stored in a separate folder in the current user`s AppData-folder:

image

The job is defined in the ScheduledJobDefinition XML-file, and there is an empty sub-folder named Output. If I manually start the job, we can see that the following is added to the Output folder:

image

Next I want to retrieve the results of the job, not by looking in the XML-files, but by using the Get-Job cmdlet. There is a gotcha to be aware of regarding this. If you open a new PowerShell session and run Get-Job, the scheduled jobs created using the PSScheduledJob cmdlets will not be available. You have to first import the PSScheduledJob module and then run Get-Job. By using Receive-Job we can get the results from our job:

image

To read about the reason for this in addition to more details about the new module you can read the “Scheduling Background Jobs in Windows PowerShell 3.0” article on the Windows PowerShell Team Blog.

Resources

How to Schedule a PowerShell Script

Sending Automated emails with Send-MailMessage, ConvertTo-HTML, and the PowerShellPack’s TaskScheduler module

Windows PowerShell Scheduled Job Module

How to Configure Clustered Tasks with Windows Server 2012

 

6 thoughts on “Working with scheduled tasks from Windows PowerShell

  1. Pingback: Working with scheduled tasks from Windows PowerShell | VMWare | EMC | Exchange | Windows

  2. Pingback: Scheduled tasks | Jacques DALBERA's IT world

  3. Pingback: Win7/W2k8 default defrag scheduled task is disabled | Jacques DALBERA's IT world