Skip to content

Advanced Operations with Task Scheduler and Trigger Control

This article explains advanced automation with Windows Task Scheduler:
conditional triggers, event-log–driven execution, registering and controlling tasks via PowerShell, and security-minded operational practices.

VariableExampleNote
<<TASK_NAME>>Daily-BackupTask name
<<SCRIPT_PATH>>C:\Scripts\backup.ps1Script path to execute
<<EVENT_ID>>4625Event ID that triggers the task
<<USERNAME>>AdministratorUser that runs the task
<<TASK_PATH>>\MyCompany\MaintenanceTask folder path in the library (optional)

When registering a task with PowerShell, you combine three primary cmdlets:

CmdletRole
New-ScheduledTaskActionDefines the program/script to run
New-ScheduledTaskTriggerDefines when to run (time/event)
Register-ScheduledTaskRegisters the full task (Action + Trigger + Settings)

① Key options for New-ScheduledTaskAction

Section titled “① Key options for New-ScheduledTaskAction”
OptionDescriptionExample
-ExecuteExecutable"powershell.exe"
-ArgumentCommand-line arguments"-NoProfile -NonInteractive -ExecutionPolicy Bypass -File <<SCRIPT_PATH>>"
-WorkingDirectoryWorking directory"C:\Scripts"
-IdIdentifier when multiple actions exist"Action1"

💡 To configure multiple actions, create several New-ScheduledTaskAction objects and pass them as an array.


② Key options for New-ScheduledTaskTrigger

Section titled “② Key options for New-ScheduledTaskTrigger”
OptionDescriptionExample
-DailyRun dailyCombine with -At 3:00AM
-WeeklyRun weekly-DaysOfWeek Monday,Wednesday
-OnceRun once-At (Get-Date).AddHours(1)
-AtStartupRun at system startup
-AtLogOnRun at user logon
-RepetitionIntervalRepeat interval(New-TimeSpan -Minutes 30)
-RepetitionDurationRepeat duration(New-TimeSpan -Days 1)
-RandomDelayJitter(New-TimeSpan -Minutes 5)
-StartBoundary / -EndBoundaryValidity window"2025-01-01T00:00:00"

⚠️ -RepetitionInterval and -RepetitionDuration are only valid for certain trigger types (e.g., Daily/Once).


③ Key options for New-ScheduledTaskSettingsSet (optional)

Section titled “③ Key options for New-ScheduledTaskSettingsSet (optional)”
OptionDescriptionExample
-AllowStartIfOnBatteriesAllow on battery power$false
-DontStopIfGoingOnBatteriesKeep running if power switches to battery$false
-StartWhenAvailableRun as soon as possible$true
-HiddenHide the task$true
-RunOnlyIfNetworkAvailableRequire network connectivity$true
-ExecutionTimeLimitMax run time(New-TimeSpan -Hours 2)
-MultipleInstancesMulti-instance policy (IgnoreNew/Parallel/Queue)"IgnoreNew"
-RestartCount / -RestartIntervalRetry count and interval3, (New-TimeSpan -Minutes 5)

💡 New-ScheduledTaskSettingsSet builds the object passed to -Settings so you can centrally control power, retry, and network conditions.


④ Key options for Register-ScheduledTask

Section titled “④ Key options for Register-ScheduledTask”
OptionDescriptionExample
-TaskNameName to register"Daily-Backup"
-TaskPathLibrary folder"\MyCompany\Maintenance"
-ActionPredefined action object$action
-TriggerPredefined trigger object$trigger
-SettingsAdditional settings (power, retry, etc.)$settings
-DescriptionAdmin description"Daily maintenance backup task"
-UserRun account"SYSTEM" or "Administrator"
-RunLevelPrivilege levelHighest
-ForceOverwrite existing

💡 A complete task is Action + Trigger + Settings combined.


Terminal window
# Define the action
$action = New-ScheduledTaskAction -Execute "powershell.exe" `
-Argument "-NoProfile -ExecutionPolicy Bypass -File <<SCRIPT_PATH>>"
# Define the trigger (daily at 03:00)
$trigger = New-ScheduledTaskTrigger -Daily -At 3:00AM
# Register the task
Register-ScheduledTask -TaskName "<<TASK_NAME>>" `
-TaskPath "<<TASK_PATH>>\Daily" `
-Action $action -Trigger $trigger `
-User "<<USERNAME>>" -Description "Run every day at 03:00"

  • Use -ExecutionPolicy Bypass only in controlled internal environments; in production prefer signed scripts.
  • Run as SYSTEM or a dedicated service account (principle of least privilege).
  • Minimum -RepetitionInterval is 1 minute; default upper bound for -RepetitionDuration is often 1 day.
  • Use -Force to overwrite existing tasks.
  • Use -RunLevel Highest only when admin privileges are required.

Step 2: Event-log triggers (with XML template)

Section titled “Step 2: Event-log triggers (with XML template)”

New-ScheduledTaskTrigger does not currently expose an event trigger (e.g., -OnEvent).
To use event-based triggers, import an XML task definition.

Register:

Terminal window
$xml = @'
<Task version="1.3" xmlns="http://schemas.microsoft.com/windows/2004/02/mit/task">
<RegistrationInfo>
<Author><<USERNAME>></Author>
<Description>Run script on Security Event ID <<EVENT_ID>></Description>
</RegistrationInfo>
<Triggers>
<EventTrigger>
<Enabled>true</Enabled>
<Subscription><![CDATA[
<QueryList>
<Query Id="0" Path="Security">
<Select Path="Security">*[System[(EventID=<<EVENT_ID>>)]]</Select>
</Query>
</QueryList>
]]></Subscription>
</EventTrigger>
</Triggers>
<Principals>
<Principal id="Author">
<UserId>SYSTEM</UserId>
<RunLevel>HighestAvailable</RunLevel>
</Principal>
</Principals>
<Settings>
<MultipleInstancesPolicy>IgnoreNew</MultipleInstancesPolicy>
<DisallowStartIfOnBatteries>false</DisallowStartIfOnBatteries>
<StopIfGoingOnBatteries>true</StopIfGoingOnBatteries>
<AllowHardTerminate>true</AllowHardTerminate>
<StartWhenAvailable>true</StartWhenAvailable>
<ExecutionTimeLimit>PT1H</ExecutionTimeLimit>
<Priority>7</Priority>
</Settings>
<Actions Context="Author">
<Exec>
<Command>C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe</Command>
<Arguments>-NoProfile -ExecutionPolicy Bypass -File "<<SCRIPT_PATH>>"</Arguments>
</Exec>
</Actions>
</Task>
'@
Register-ScheduledTask -TaskName "<<TASK_NAME>>" -TaskPath "<<TASK_PATH>>\OnEvent" -Xml $xml -User "SYSTEM"

Step 3: Combine triggers with run conditions

Section titled “Step 3: Combine triggers with run conditions”

Define Conditions (power, network, idle) using New-ScheduledTaskSettingsSet.

Terminal window
$settings = New-ScheduledTaskSettingsSet `
-AllowStartIfOnBatteries:$false `
-DontStopIfGoingOnBatteries:$false `
-StartWhenAvailable:$true `
-Hidden:$false `
-RunOnlyIfNetworkAvailable:$true `
-ExecutionTimeLimit (New-TimeSpan -Hours 2)
Register-ScheduledTask -TaskName "<<TASK_NAME>>_Cond" `
-TaskPath "<<TASK_PATH>>\Conditional" `
-Action $action -Trigger $trigger -Settings $settings `
-User "<<USERNAME>>" -Description "Conditional task (requires network / AC power)"
ConditionSettingDescription
AC power only-AllowStartIfOnBatteries:$falseDo not run on battery
Network required-RunOnlyIfNetworkAvailable:$trueSkip when network is down
Idle-onlyXML or COMNative PowerShell support is limited
Max run time-ExecutionTimeLimitPrevents run-away executions
Retry policyXML or repeated triggersSome limits when using only PowerShell

Terminal window
# List tasks
Get-ScheduledTask | Where-Object TaskPath -like "<<TASK_PATH>>*"
# Enable / disable
Enable-ScheduledTask -TaskName "<<TASK_NAME>>"
Disable-ScheduledTask -TaskName "<<TASK_NAME>>"
# Inspect runtime state
Get-ScheduledTaskInfo -TaskName "<<TASK_NAME>>" |
Select-Object TaskName, NextRunTime, LastRunTime, LastTaskResult

The Microsoft-Windows-TaskScheduler/Operational channel may be disabled by default.
Enable it for troubleshooting and detailed history:

Terminal window
wevtutil sl Microsoft-Windows-TaskScheduler/Operational /e:true

Terminal window
# Latest execution result
Get-ScheduledTaskInfo -TaskName "<<TASK_NAME>>"
# Operational log filtered by task name
Get-WinEvent -LogName "Microsoft-Windows-TaskScheduler/Operational" -MaxEvents 50 |
Where-Object { $_.Message -match "<<TASK_NAME>>" } |
Select-Object TimeCreated, Id, Message | Format-Table -AutoSize
CauseFix
Insufficient privilegesReview run account permissions / use a service account
Execution Policy blocksUse signed scripts or -ExecutionPolicy Bypass in controlled envs
Missing TaskPath / descriptionSet -TaskPath and -Description for clarity
Event trigger not firingRe-check XML and event filter
Conflicting triggers/conditionsRevisit trigger logic and Settings

  • Run as SYSTEM or a dedicated service account; enforce least privilege.
  • Add logging and exception handling in scripts to record success/failure.
  • Template XML task definitions and version them in Git (e.g., GitHub).
  • Periodically monitor with Get-ScheduledTaskInfo and alert on anomalies.
  • Remove obsolete tasks with Unregister-ScheduledTask to keep the library tidy.

Beyond simple schedules, Task Scheduler enables powerful automation through event-driven triggers, conditional run controls, and PowerShell integration.
Managing definitions and monitoring as code improves reproducibility, governance, and operational security.