In the article Calling PowerShell scripts from Task Scheduler I described how to call a PowerShell script from the scheduled task. Here I go a step further and let the script "install" itself by creating a schedule in Task Scheduler.
The following function uses the command-line tool schtasks.exe to create a schedule that runs Monday to Friday at 8:00 a.m.
function CreateSchedule() {
$logFile = join-path (pwd) "Scheduling.log" #use absolute path in the scheduled task
$taskName = "Daily Job"
$thisScript = $PSCommandPath
$callParams = @("/Create",
"/TN", $taskName,
"/SC", "weekly",
"/D", "MON,TUE,WED,THU,FRI",
"/ST", "08:00",
"/TR", ("powershell.exe -File `"$thisScript`" -ConsoleOutputFile `"$logFile`"" -replace '"', '\"'),
"/F", #force
"/RU", "system") #run under the system account
Log "schtasks.exe", $callParams
$o = & "schtasks.exe" $callParams
Log $o
}
Note the escaping of quotation marks in the task command: "powershell.exe -File `"$thisScript`" -ConsoleOutputFile `"$logFile`"" -replace '"', '\"'
We use PowerShell to call a command to create a schedule that calls another command. Each of the steps requires its own escaping of quotation marks.
If we can install the script, we should be able to uninstall it too:
function DeleteSchedule() {
$taskName = "Daily Job"
$callParams = @("/Delete",
"/TN", $taskName,
"/F") #force
Log "schtasks.exe", $callParams
$o = & "schtasks.exe" $callParams
Log $o
}
Example
Below is a full example of a script including the scaffolding of parameters declaration and main()
. The function DoTheJob()
would do the actual work. The parameter ConsoleOutputFile
and method Log()
are described in the article Calling PowerShell scripts from Task Scheduler.
[CmdletBinding(DefaultParametersetName="run")]
param(
[Parameter(ParameterSetName='install')]
[switch]$Install,
[Parameter(ParameterSetName='uninstall')]
[switch]$Uninstall,
#Path to the text file to which the standard output of the script will be redirected. If omitted, the output is printed to the host.
[string]$ConsoleOutputFile
)
function Main() {
if($Install) {
DeleteSchedule
CreateSchedule
} elseif($Uninstall) {
DeleteSchedule
} else {
DoTheJob
}
}
function Log($msg) {
if(($ConsoleOutputFile -eq $null) -or ($ConsoleOutputFile -eq "")) {
Write-Host $msg
} else {
if(-not (Test-Path $ConsoleOutputFile)) {
New-Item $ConsoleOutputFile -ItemType file -Force #creates the file including any necessary directories
}
Add-Content $ConsoleOutputFile $msg
}
}
function DoTheJob() {
$result = dir #any action that must be scheduled
Log $result
}
function CreateSchedule() {
$logFile = join-path (pwd) "Scheduling.log" #use absolute path in the scheduled task
$taskName = "Daily Job"
$thisScript = $PSCommandPath
$callParams = @("/Create",
"/TN", $taskName,
"/SC", "weekly",
"/D", "MON,TUE,WED,THU,FRI",
"/ST", "08:00",
"/TR", ("powershell.exe -File `"$thisScript`" -ConsoleOutputFile `"$logFile`"" -replace '"', '\"'),
"/F", #force
"/RU", "system") #run under the system account
Log "schtasks.exe", $callParams
$o = & "schtasks.exe" $callParams
Log $o
}
function DeleteSchedule() {
$taskName = "Daily Job"
$callParams = @("/Delete",
"/TN", $taskName,
"/F") #force
Log "schtasks.exe", $callParams
$o = & "schtasks.exe" $callParams
Log $o
}
Main #run the script