WindowsschtasksPowerShell

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.

11 min read·Updated April 2026

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

GUITask Scheduler GUI — taskschd.msc — best for one-off tasks and visual inspection
CLIschtasks.exe — built-in command line tool, good for scripting simple tasks
PSPowerShell New-ScheduledTask — most flexible, supports all features, preferred for automation
Important: Unlike cron, Windows scheduled tasks run in the context of a specific user account. Tasks set to run whether the user is logged in or not require a password or a service account (SYSTEM, LOCAL SERVICE, NETWORK SERVICE).

2. 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

FlagDescription
/SCSchedule type: MINUTE, HOURLY, DAILY, WEEKLY, MONTHLY, ONCE, ONSTART, ONLOGON, ONIDLE, ONEVENT
/MOModifier — for MINUTE: interval (1-1439), DAILY: days between (1-365), WEEKLY: weeks between (1-52)
/DDay of week (MON-SUN) for WEEKLY, or day-of-month (1-31) for MONTHLY
/MMonth for MONTHLY (JAN-DEC, or * for all)
/STStart time in HH:MM (24h format)
/TNTask name (path, e.g. \MyFolder\TaskName)
/TRTask to run — command or script path
/RURun as user: SYSTEM, LOCAL SERVICE, NETWORK SERVICE, or username
/SDStart date (MM/DD/YYYY)
/EDEnd 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:

DescriptionCronschtasks /SC …
Every minute* * * * *MINUTE /MO 1
Every 5 minutes*/5 * * * *MINUTE /MO 5
Every hour0 * * * *HOURLY /MO 1
Daily at 9 AM0 9 * * *DAILY /ST 09:00
Weekdays at 9 AM0 9 * * 1-5WEEKLY /D MON,TUE,WED,THU,FRI /ST 09:00
Every Sunday midnight0 0 * * 0WEEKLY /D SUN /ST 00:00
1st of month at 1 AM0 1 1 * *MONTHLY /D 1 /ST 01:00
January 1st at 2 AM0 2 1 1 *MONTHLY /M JAN /D 1 /ST 02:00
Note: Windows Task Scheduler does not support sub-minute scheduling directly. For sub-minute intervals, use a task that runs a script with a loop (sleep-based) or use a dedicated scheduler like Quartz.NET.

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 $action

Query 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"
Tip: Store task XML in your repo alongside your scripts. On deployment, import the task with schtasks or PowerShell so task scheduling is reproducible and code-reviewed like any other infrastructure change.

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

01

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.

02

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.

03

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.

04

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.

05

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.

06

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.