Windows Task Scheduler Guide: schtasks, XML, and Cron Equivalents
Windows Task Scheduler is the native cron equivalent for Windows. It supports complex schedules via GUI, schtasks.exe CLI, PowerShell, or XML definitions. This guide covers all three approaches and maps common cron expressions to their Windows equivalents.
Table of Contents
1. Task Scheduler Overview
Windows Task Scheduler (taskschd.msc) has been part of Windows since Windows 98. The modern version (Task Scheduler 2.0, introduced in Vista/Server 2008) supports multiple triggers per task, conditions, security contexts, and rich XML definitions.
Three ways to create scheduled tasks
taskschd.msc — best for one-off tasks and visual inspectionschtasks.exe — built-in command line tool, good for scripting simple tasksNew-ScheduledTask — most flexible, supports all features, preferred for automation2. schtasks.exe CLI
schtasks.exe is the command-line interface for Task Scheduler. Run it in an elevated (Administrator) Command Prompt.
Create a task
# Run backup.bat daily at 2 AM schtasks /Create /SC DAILY /TN "Daily Backup" /TR "C:\Scripts\backup.bat" /ST 02:00 # Run every 30 minutes schtasks /Create /SC MINUTE /MO 30 /TN "Health Check" /TR "C:\Scripts\check.ps1" # Run weekly on Monday at 9 AM schtasks /Create /SC WEEKLY /D MON /ST 09:00 /TN "Weekly Report" /TR "C:\Scripts\report.exe" # Run as SYSTEM (no password required) schtasks /Create /SC DAILY /ST 01:00 /TN "DB Cleanup" /TR "C:\Scripts\cleanup.bat" /RU SYSTEM
Query, run, and delete
# List all scheduled tasks schtasks /Query /FO LIST /V # Show a specific task schtasks /Query /TN "Daily Backup" /FO LIST /V # Run a task immediately schtasks /Run /TN "Daily Backup" # Delete a task schtasks /Delete /TN "Daily Backup" /F # Enable / disable a task schtasks /Change /TN "Daily Backup" /ENABLE schtasks /Change /TN "Daily Backup" /DISABLE
Key flags reference
| Flag | Description |
|---|---|
| /SC | Schedule type: MINUTE, HOURLY, DAILY, WEEKLY, MONTHLY, ONCE, ONSTART, ONLOGON, ONIDLE, ONEVENT |
| /MO | Modifier — for MINUTE: interval (1-1439), DAILY: days between (1-365), WEEKLY: weeks between (1-52) |
| /D | Day of week (MON-SUN) for WEEKLY, or day-of-month (1-31) for MONTHLY |
| /M | Month for MONTHLY (JAN-DEC, or * for all) |
| /ST | Start time in HH:MM (24h format) |
| /TN | Task name (path, e.g. \MyFolder\TaskName) |
| /TR | Task to run — command or script path |
| /RU | Run as user: SYSTEM, LOCAL SERVICE, NETWORK SERVICE, or username |
| /SD | Start date (MM/DD/YYYY) |
| /ED | End date (MM/DD/YYYY) |
3. Schedule Types & Triggers
Windows Task Scheduler supports both time-based triggers (like cron) and event-based triggers that have no cron equivalent.
Time-based
- •MINUTE — every N minutes (1-1439)
- •HOURLY — every N hours
- •DAILY — every N days at a specific time
- •WEEKLY — on specific days of the week
- •MONTHLY — on specific days/months
- •ONCE — run once at a specific time
Event-based (no cron equivalent)
- •ONSTART — when the computer starts (no user login needed)
- •ONLOGON — when a specific user logs in
- •ONIDLE — after computer is idle for N minutes
- •ONEVENT — on a specific Windows Event Log event (by query XPath)
4. Cron → Windows Task Scheduler Mapping
Windows Task Scheduler does not use cron expression syntax. Here's how common cron patterns map to schtasks.exe flags:
| Description | Cron | schtasks /SC … |
|---|---|---|
| Every minute | * * * * * | MINUTE /MO 1 |
| Every 5 minutes | */5 * * * * | MINUTE /MO 5 |
| Every hour | 0 * * * * | HOURLY /MO 1 |
| Daily at 9 AM | 0 9 * * * | DAILY /ST 09:00 |
| Weekdays at 9 AM | 0 9 * * 1-5 | WEEKLY /D MON,TUE,WED,THU,FRI /ST 09:00 |
| Every Sunday midnight | 0 0 * * 0 | WEEKLY /D SUN /ST 00:00 |
| 1st of month at 1 AM | 0 1 1 * * | MONTHLY /D 1 /ST 01:00 |
| January 1st at 2 AM | 0 2 1 1 * | MONTHLY /M JAN /D 1 /ST 02:00 |
5. PowerShell Scheduling
PowerShell's ScheduledTasks module (available since Windows 8/Server 2012 R2) provides more control than schtasks.exe, including support for multiple triggers and advanced conditions.
Basic pattern: action + trigger + settings + registration
# Step 1: Define the action (what to run)
$action = New-ScheduledTaskAction `
-Execute "powershell.exe" `
-Argument "-NonInteractive -File C:\Scripts\cleanup.ps1" `
-WorkingDirectory "C:\Scripts"
# Step 2: Define the trigger (when to run)
$trigger = New-ScheduledTaskTrigger `
-Daily `
-At "02:00AM"
# Step 3: Define settings (run even if on battery, etc.)
$settings = New-ScheduledTaskSettingsSet `
-ExecutionTimeLimit (New-TimeSpan -Hours 1) `
-RestartCount 3 `
-RestartInterval (New-TimeSpan -Minutes 5) `
-StartWhenAvailable
# Step 4: Register the task
Register-ScheduledTask `
-TaskName "Daily Cleanup" `
-TaskPath "\MyCompany\" `
-Action $action `
-Trigger $trigger `
-Settings $settings `
-RunLevel Highest `
-User "SYSTEM"Trigger examples
# Every 30 minutes (repetition trigger)
$trigger = New-ScheduledTaskTrigger -Once -At "00:00" `
-RepetitionInterval (New-TimeSpan -Minutes 30) `
-RepetitionDuration ([TimeSpan]::MaxValue)
# Weekly on Monday and Wednesday at 9 AM
$trigger = New-ScheduledTaskTrigger `
-Weekly `
-DaysOfWeek Monday, Wednesday `
-At "09:00AM"
# On system startup (requires SYSTEM or elevated)
$trigger = New-ScheduledTaskTrigger -AtStartup
# On user logon
$trigger = New-ScheduledTaskTrigger -AtLogOn -User "DOMAIN\username"
# Multiple triggers on one task
$t1 = New-ScheduledTaskTrigger -Daily -At "08:00AM"
$t2 = New-ScheduledTaskTrigger -Daily -At "08:00PM"
Register-ScheduledTask -TaskName "Twice Daily" -Trigger $t1, $t2 -Action $actionQuery and manage tasks
# List all tasks Get-ScheduledTask | Select-Object TaskName, State, TaskPath # Get a specific task Get-ScheduledTask -TaskName "Daily Cleanup" | Get-ScheduledTaskInfo # Start / stop Start-ScheduledTask -TaskName "Daily Cleanup" Stop-ScheduledTask -TaskName "Daily Cleanup" # Enable / disable Enable-ScheduledTask -TaskName "Daily Cleanup" Disable-ScheduledTask -TaskName "Daily Cleanup" # Remove a task Unregister-ScheduledTask -TaskName "Daily Cleanup" -Confirm:$false
6. XML Task Definitions
Task Scheduler stores tasks as XML files in C:\Windows\System32\Tasks\. You can export, edit, and import tasks as XML — useful for version-controlling scheduled tasks alongside your code.
Minimal XML task definition
<?xml version="1.0" encoding="UTF-16"?>
<Task version="1.2"
xmlns="http://schemas.microsoft.com/windows/2004/02/mit/task">
<Triggers>
<!-- Daily at 2 AM — equivalent to cron: 0 2 * * * -->
<CalendarTrigger>
<StartBoundary>2026-01-01T02:00:00</StartBoundary>
<ScheduleByDay>
<DaysInterval>1</DaysInterval>
</ScheduleByDay>
</CalendarTrigger>
</Triggers>
<Actions Context="Author">
<Exec>
<Command>powershell.exe</Command>
<Arguments>-NonInteractive -File C:\Scripts\backup.ps1</Arguments>
<WorkingDirectory>C:\Scripts</WorkingDirectory>
</Exec>
</Actions>
<Principals>
<Principal id="Author">
<UserId>S-1-5-18</UserId><!-- SYSTEM -->
<RunLevel>HighestAvailable</RunLevel>
</Principal>
</Principals>
<Settings>
<ExecutionTimeLimit>PT1H</ExecutionTimeLimit><!-- 1 hour max -->
<StartWhenAvailable>true</StartWhenAvailable>
<RestartCount>3</RestartCount>
<RestartInterval>PT5M</RestartInterval>
</Settings>
</Task>Import/export via CLI
# Export a task to XML (for version control) schtasks /Query /TN "Daily Backup" /XML > daily-backup-task.xml # Import a task from XML schtasks /Create /TN "Daily Backup" /XML daily-backup-task.xml # PowerShell: export + import Export-ScheduledTask -TaskName "Daily Backup" | Out-File daily-backup.xml Register-ScheduledTask -Xml (Get-Content daily-backup.xml | Out-String) -TaskName "Daily Backup"
7. Conditions & Settings
Task Scheduler has a rich set of conditions and settings that cron doesn't offer natively.
Conditions
- ✓Only start if the computer is idle for N minutes
- ✓Only start if connected to AC power (useful for laptops)
- ✓Only start if a specific network connection is available
- ✓Stop if the computer ceases to be idle
Settings
- ✓Run task as soon as possible after a scheduled start is missed (StartWhenAvailable)
- ✓Stop the task if it runs longer than N hours/minutes (ExecutionTimeLimit)
- ✓If the running task does not end when requested, force it to stop
- ✓Restart on failure: up to N times, with N-minute intervals (RestartCount/RestartInterval)
- ✓Delete the task automatically if it is not scheduled to run again
- ✓Run only if the user is logged on / whether or not user is logged on
- ✓Do not store password (task runs with limited network access if not domain-joined)
8. Best Practices
Use SYSTEM or a dedicated service account
Running tasks as an interactive user means they fail if the user is logged out or changes their password. Prefer SYSTEM for local tasks or a dedicated service account (with 'Log on as a batch job' rights) for domain environments.
Always set ExecutionTimeLimit
Tasks that hang will block future runs if ConcurrencyPolicy is set to queue. Set a realistic timeout (e.g., PT1H for 1 hour) and pair it with "Stop the task if it runs longer than" to prevent runaway processes.
Enable StartWhenAvailable for critical jobs
If the machine is off at the scheduled time (e.g., maintenance window or laptop sleep), the task will be skipped by default. Enable StartWhenAvailable to run it as soon as the machine comes back online.
Log output explicitly — Task Scheduler doesn't capture stdout
Unlike cron (which can email stdout), Task Scheduler discards console output by default. Always redirect output in your script: cmd /c script.bat >> C:\Logs\task.log 2>&1 or use Start-Transcript in PowerShell.
Store task XML in version control
Export task definitions as XML and commit them to your repo. This makes scheduled tasks reproducible, auditable, and deployable as infrastructure-as-code. Use schtasks /Create /XML on deployment.
Use task folders for organization
Create task folders under the Task Scheduler Library (e.g., \MyApp\Maintenance\) to group related tasks. This makes bulk management (enable, disable, delete) easier and avoids name collisions.
Convert cron expressions to human-readable descriptions
Use CronExpression.tools to validate cron syntax, see the next 10 run times, and generate GitHub Actions workflow YAML.