Windows Task Scheduler: Advanced Triggers, Conditions and Hidden Tasks
Advanced Windows Task Scheduler configuration. Event-based triggers, conditions, run-on-demand without UAC, find hidden tasks and debug failed scheduled jobs.
Beyond basic scheduling, Task Scheduler has powerful trigger types and execution conditions that most admins never use.
Event-Based Triggers
Run a task when a specific event appears in Event Log:
# Trigger on failed logon attempt (Event ID 4625)
$trigger = New-ScheduledTaskTrigger -OnEvent `
-Subscription '<QueryList><Query><Select Path="Security">*[System[EventID=4625]]</Select></Query></QueryList>' `
-Delay "00:01:00" # wait 1 minute after event
$action = New-ScheduledTaskAction -Execute "powershell.exe" `
-Argument '-Command "Send-MailMessage -To admin@company.com -Subject \"Failed Login Detected\" -From server@company.com -SmtpServer smtp.company.com"'
Register-ScheduledTask -TaskName "Alert-FailedLogin" `
-Action $action -Trigger $trigger -RunLevel Highest
# Trigger on new USB device connected (Event ID 2003)
$trigger = New-ScheduledTaskTrigger -OnEvent `
-Subscription '<QueryList><Query><Select Path="Microsoft-Windows-DriverFrameworks-UserMode/Operational">*[System[EventID=2003]]</Select></Query></QueryList>'
Idle and Workload Conditions
# Only run when PC has been idle for 10 minutes
$settings = New-ScheduledTaskSettingsSet `
-RunOnlyIfIdle `
-IdleDuration "00:10:00" `
-IdleWaitTimeout "04:00:00" # wait up to 4 hours for idle
# Stop if PC wakes from idle
$settings = New-ScheduledTaskSettingsSet `
-RunOnlyIfIdle -StopIfGoingOffIdle
# Only run on AC power
$settings = New-ScheduledTaskSettingsSet -RunOnlyIfNetworkAvailable
Register-ScheduledTask -TaskName "IdleTask" `
-Action $action -Trigger $trigger -Settings $settings
Run Without UAC Prompt
# Run as SYSTEM (no UAC, no user required)
$principal = New-ScheduledTaskPrincipal `
-UserId "NT AUTHORITY\SYSTEM" `
-LogonType ServiceAccount `
-RunLevel Highest
Register-ScheduledTask -TaskName "SilentAdminTask" `
-Action $action -Trigger $trigger -Principal $principal
Find and Audit Hidden Tasks
Malware often creates tasks in unusual locations:
# Tasks in root (user-created) — most legitimate tasks
Get-ScheduledTask | Where-Object {$_.TaskPath -eq "\"} |
Select-Object TaskName, State, @{n='Action';e={$_.Actions.Execute}}
# Tasks NOT in \Microsoft\ paths
Get-ScheduledTask | Where-Object {$_.TaskPath -notlike "*\Microsoft\*"} |
Select-Object TaskPath, TaskName, @{n='Action';e={$_.Actions.Execute}}
# Tasks running from temp or user profile (suspicious)
Get-ScheduledTask | Where-Object {
$_.Actions.Execute -like "*\Temp\*" -or
$_.Actions.Execute -like "*\AppData\*" -or
$_.Actions.Execute -like "*\Users\*"
} | Select-Object TaskName, @{n='Executable';e={$_.Actions.Execute}}
Task History and Debugging
# Enable history if disabled
wevtutil sl Microsoft-Windows-TaskScheduler/Operational /e:true
# View recent task runs (all tasks)
Get-WinEvent -LogName "Microsoft-Windows-TaskScheduler/Operational" -MaxEvents 50 |
Where-Object {$_.Id -in @(100,101,102,103,200,201)} |
Select-Object TimeCreated, Id,
@{n='Task';e={$_.Properties[0].Value}},
@{n='Result';e={$_.Properties[1].Value}} |
Format-Table -AutoSize
# Why did a task fail?
Get-ScheduledTaskInfo -TaskName "DailyScript" |
Select-Object LastRunTime, LastTaskResult, NextRunTime
# Task result codes
# 0x0 = Success
# 0x1 = Incorrect function
# 0x41301 = Still running
# 0x41303 = Not yet run
# 0x41306 = Task stopped
Disable/Pause All Tasks (Emergency)
# Disable all non-Microsoft tasks
Get-ScheduledTask | Where-Object {$_.TaskPath -notlike "*\Microsoft\*"} |
Disable-ScheduledTask
# Re-enable
Get-ScheduledTask | Where-Object {$_.TaskPath -notlike "*\Microsoft\*"} |
Enable-ScheduledTask
Summary
Event triggers with <QueryList> XML. Idle conditions with -RunOnlyIfIdle. Run silently as SYSTEM with SYSTEM principal. Audit all non-Microsoft tasks for malware. Enable history with wevtutil sl for debugging. Result 0x0 = success.
Frequently Asked Questions
My task shows LastTaskResult 0x1 — what does that mean?
0x1 = the PowerShell/batch script returned exit code 1. Usually means the script encountered an error. Add -ErrorAction Stop and proper error handling to get useful exit codes.
Task runs fine manually but fails on schedule — common causes?
- Working directory wrong — use full paths in scripts
- Environment variables different for SYSTEM vs user
- Missing modules — add explicit
Import-Modulein the script - Network drives not available when SYSTEM runs
- Execution policy — add
-ExecutionPolicy Bypassto the PowerShell action
Can I run a scheduled task under a user account without that user being logged in?
Yes — set logon type to Password and provide credentials. The account needs "Log on as batch job" right: secpol.msc → Local Policies → User Rights Assignment.