Suppose you found or created one of those valuable scripts but want to run it on a schedule or even schedule itself. Whilst there is this wonderful Powershell Pack that includes a module to utilize the task scheduler from Powershell, this article uses the standard “Schtasks” utility. We assume some familiarity with the task scheduler, use “Schtasks /?” to find more information on its usage.
There are two things to pay attention to; the length of the schedule command and spaces in path names.
A command cannot exceed 260 characters. Running a Powershell command from the DPM binary path requires ~80 character script path, similar for the console initialization file and a few dozen for the complete “Schtasks” command. So we have a ~200 character command line leaving ample room for parameters you may need to pass to the scheduled script. Here are some ways to overcome that;
There is a challenge in scheduling commands with spaces in the path names or parameters. The sample script is best used “as is” with regards to the amount of escaped quotes. These are necessary because quotes get removed during interpretation by the current Powershell, by the task scheduler and again by Powershell at execution time. This sample executes as ‘Local System’ which suites most situations but see also “Schtasks create /?” for other options.
To schedule itself run script with the –schedule switch as; .\script.ps1 –schedule
param ([switch] $schedule, [string]$ScriptToSchedule=””) # If the snapin is the only thing you need… load DPM snap-in regardless and clear the error Add-PSSnapin -name Microsoft.DataProtectionManager.PowerShell -erroraction SilentlyContinue $Error.Clear() if ($schedule) { # Note that we do not use –PSconsolefile because we loaded # the required snap-in ourselves and have no other needs if ($ScriptToSchedule –eq “”) { $taskname = $myinvocation.mycommand.definition -replace '\W','_' $thisscript = "`"`"`"`"powershell`"`"`" -noninteractive -nologo -command `"`"`"&{$($myinvocation.mycommand.definition)}`"`"`"" } else { if (!(Test-Path $scripttoschedule)) {Throw "File not found!";exit} $taskname = $ScriptToSchedule -replace '\W','_' $thisscript = "`"`"`"`"powershell`"`"`" -noninteractive -nologo -command `"`"`"&{$ScriptToSchedule}`"`"`"" } $msg = $null $msg = @(schtasks /create /F /TN $taskname /SC "DAILY" /RU "System" /ST 06:00 /TR "$thisscript") if ($msg -inotmatch "SUCCESS") {Throw "ERROR: scheduler reported a failure"} else { schtasks /Query /TN "$taskname" /V /FO LIST } exit } Write-Host "Whatever the script is supposed to be doing goes here"
param ([switch] $schedule, [string]$ScriptToSchedule=””)
# If the snapin is the only thing you need… load DPM snap-in regardless and clear the error Add-PSSnapin -name Microsoft.DataProtectionManager.PowerShell -erroraction SilentlyContinue $Error.Clear()
if ($schedule) {
# Note that we do not use –PSconsolefile because we loaded # the required snap-in ourselves and have no other needs
if ($ScriptToSchedule –eq “”) { $taskname = $myinvocation.mycommand.definition -replace '\W','_' $thisscript = "`"`"`"`"powershell`"`"`" -noninteractive -nologo -command `"`"`"&{$($myinvocation.mycommand.definition)}`"`"`"" } else { if (!(Test-Path $scripttoschedule)) {Throw "File not found!";exit} $taskname = $ScriptToSchedule -replace '\W','_' $thisscript = "`"`"`"`"powershell`"`"`" -noninteractive -nologo -command `"`"`"&{$ScriptToSchedule}`"`"`"" } $msg = $null $msg = @(schtasks /create /F /TN $taskname /SC "DAILY" /RU "System" /ST 06:00 /TR "$thisscript") if ($msg -inotmatch "SUCCESS") {Throw "ERROR: scheduler reported a failure"} else { schtasks /Query /TN "$taskname" /V /FO LIST } exit }
Write-Host "Whatever the script is supposed to be doing goes here"
Having dealt with various conditions my personal favorite method is writing a parameter file and read the parameter file from within the scheduled task. This way you can easily stay below 260 characters and no special consideration or limitations on parameter data.