Tuesday, February 1, 2011

Scheduling Tasks in PowerShell for Windows Server 2008 -- Part 1: Monthly Task

Windows Server 2008 updates one of my biggest complaints in Windows Server 2003 relating to scheduling automated tasks programatically. I have always appreciated the ease of doing this in Linux/UNIX via crontab. That ease was just not there in Windows Server 2003 as at is very clunky. However, I feel that creating a scheduled task in Windows Server 2003 manually is much easier and faster than Windows Server 2008 -- but that's me. In the example below, I create a monthly scheduled task that occurs at 6 am on the 15th of the month starting in February 2011. I am storing the task in a subfolder off the root in Scheduled Tasks that I manually created to segregate the task from other application registrations. The task will run under another security context than the one that created the task. I would prefer to capture the password securely for that context and supply it that way to the RegisterTaskDefinition but I have not discovered how to perform this with the provider. To provide a modicum of security, I clear the $password variable at the end of the script. To reduce security risks in your environment, always execute scripts with the least security privilege required to perform the function.

In future posts, I will provide further examples that show the different intervals that you can schedule tasks. This example is a basic task as there are many areas where you can fine tune the task.
# Parameters to modify
$taskName = "Export-InterestingInformation.ps1"
$taskWorkingDirectory = "C:\PowerShell"
$taskAuthor = "ad\myaccount"
$taskDescription = "The Monthly Interesting Information Report"
$taskSecurityPrincipal = "ad\reporting"
$taskSheduledTaskFolder = "\MyTasks"
$startTime = (Get-Date "02/15/2011 06:00:00" -Format s)

# Would like to use -asSecureString but RegisterTaskDefinition does not accept it
# Look over your shoulder before typing
$password = Read-Host -prompt "$taskSecurityPrincipal Password"

# The meaty parts

$taskService = New-Object -ComObject Schedule.Service
$taskService.Connect()

$rootFolder = $taskService.GetFolder($taskSheduledTaskFolder)

$taskDefinition = $taskService.NewTask(0)

$registrationInformation = $taskDefinition.RegistrationInfo
$registrationInformation.Description = $taskDescription
$registrationInformation.Author = $taskAuthor

$taskPrincipal = $taskDefinition.Principal
$taskPrincipal.LogonType = 1
$taskPrincipal.UserID = $taskSecurityPrincipal
$taskPrincipal.RunLevel = 0

$taskSettings = $taskDefinition.Settings
$taskSettings.StartWhenAvailable = $true
$taskSettings.RunOnlyIfNetworkAvailable = $true
$taskSettings.Priority = 7
$taskSettings.ExecutionTimeLimit = "PT2H"

$taskTriggers = $taskDefinition.Triggers

$executionTrigger = $taskTriggers.Create(4) 
$executionTrigger.DaysOfMonth = 16384 # http://msdn.microsoft.com/en-us/library/aa380735(v=vs.85).aspx
$executionTrigger.StartBoundary = $startTime

$taskAction = $taskDefinition.Actions.Create(0)
$taskAction.Path = "%SystemRoot%\system32\WindowsPowerShell\v1.0\powershell.exe"
$taskAction.Arguments = "-command `"$taskWorkingDirectory\$taskName`""
$taskAction.WorkingDirectory = $taskWorkingDirectory

# 6 == Task Create or Update
# 1 == Password must be supplied at registration
$rootFolder.RegisterTaskDefinition($taskName, $taskDefinition, 6, $taskSecurityPrincipal, $password, 1)

# Since we captured this in plain text I am going to nuke the value
# Not 100% security
Clear-Variable -name password

No comments:

Post a Comment