Windows Server

Task Scheduler: Automation on Windows Server

Create and manage automated tasks on Windows Server with Task Scheduler. Windows equivalent of Linux cron for backups, scripts and maintenance.

Task Scheduler is Windows equivalent of cron. It allows you to run scripts, commands and programs automatically at scheduled times or in response to system events.


Open Task Scheduler

# Via run
taskschd.msc

# Via PowerShell
Get-ScheduledTask | Where-Object State -eq "Running"

Create a Task via PowerShell

PowerShell is the most reliable and scriptable method to create tasks.

Basic Structure

# 1. Define action (what to execute)
$action = New-ScheduledTaskAction `
  -Execute "powershell.exe" `
  -Argument "-NonInteractive -ExecutionPolicy Bypass -File C:\Scripts\backup.ps1"

# 2. Define trigger (when to execute)
$trigger = New-ScheduledTaskTrigger -Daily -At "02:00AM"

# 3. Define settings
$settings = New-ScheduledTaskSettingsSet `
  -ExecutionTimeLimit (New-TimeSpan -Hours 2) `
  -RestartCount 3 `
  -RestartInterval (New-TimeSpan -Minutes 5)

# 4. Register the task
Register-ScheduledTask `
  -TaskName "Nightly Backup" `
  -Action $action `
  -Trigger $trigger `
  -Settings $settings `
  -RunLevel Highest `
  -User "SYSTEM"

Trigger Types

Fixed Schedule (daily, weekly, monthly)

# Every day at 3:00 AM
$trigger = New-ScheduledTaskTrigger -Daily -At "03:00AM"

# Every Monday at 8:30 AM
$trigger = New-ScheduledTaskTrigger -Weekly -WeeksInterval 1 `
  -DaysOfWeek Monday -At "08:30AM"

# First day of month at 00:00
$trigger = New-ScheduledTaskTrigger -Monthly -DaysOfMonth 1 -At "00:00AM"

# Every hour (use RepetitionInterval)
$trigger = New-ScheduledTaskTrigger -Once -At (Get-Date) `
  -RepetitionInterval (New-TimeSpan -Hours 1) `
  -RepetitionDuration ([TimeSpan]::MaxValue)

At Boot / Login

# At system startup
$trigger = New-ScheduledTaskTrigger -AtStartup

# At specific user login
$trigger = New-ScheduledTaskTrigger -AtLogOn -User "DOMAIN\user"

On System Event

# When specific event is written to log
$trigger = New-ScheduledTaskTrigger -AtEvent `
  -LogName "System" -Source "Service Control Manager" -EventId 7036

Practical Examples

SQL Server Express Backup (no SQL Agent)

# Create backup script
$backupScript = @'
$date = Get-Date -Format "yyyyMMdd_HHmm"
$backupPath = "C:\Backup\DB_$date.bak"
Invoke-Sqlcmd -ServerInstance "localhost" -Query "BACKUP DATABASE MyDb TO DISK='$backupPath' WITH FORMAT, COMPRESSION"
# Delete backups older than 7 days
Get-ChildItem "C:\Backup\*.bak" | Where-Object LastWriteTime -lt (Get-Date).AddDays(-7) | Remove-Item
'@
$backupScript | Out-File "C:\Scripts\backup-sql.ps1" -Encoding utf8

# Create task
$action = New-ScheduledTaskAction -Execute "powershell.exe" `
  -Argument "-NonInteractive -ExecutionPolicy Bypass -File C:\Scripts\backup-sql.ps1"
$trigger = New-ScheduledTaskTrigger -Daily -At "02:00AM"
Register-ScheduledTask -TaskName "SQL Nightly Backup" `
  -Action $action -Trigger $trigger -User "SYSTEM" -RunLevel Highest

Weekly IIS Log Cleanup

$cleanScript = @'
$logPath = "C:\inetpub\logs\LogFiles"
Get-ChildItem $logPath -Recurse -Filter "*.log" |
  Where-Object LastWriteTime -lt (Get-Date).AddDays(-30) |
  Remove-Item -Force
'@
$cleanScript | Out-File "C:\Scripts\clean-iis-logs.ps1" -Encoding utf8

$action = New-ScheduledTaskAction -Execute "powershell.exe" `
  -Argument "-NonInteractive -ExecutionPolicy Bypass -File C:\Scripts\clean-iis-logs.ps1"
$trigger = New-ScheduledTaskTrigger -Weekly -WeeksInterval 1 `
  -DaysOfWeek Sunday -At "03:00AM"
Register-ScheduledTask -TaskName "IIS Log Cleanup" `
  -Action $action -Trigger $trigger -User "SYSTEM" -RunLevel Highest

Auto-Restart Service if Offline

$watchScript = @'
$service = "W3SVC"
if ((Get-Service $service).Status -ne "Running") {
  Start-Service $service
  Write-EventLog -LogName Application -Source "TaskScheduler" `
    -EventId 1001 -EntryType Warning -Message "Service $service restarted automatically"
}
'@
$watchScript | Out-File "C:\Scripts\watch-iis.ps1" -Encoding utf8

$action = New-ScheduledTaskAction -Execute "powershell.exe" `
  -Argument "-NonInteractive -ExecutionPolicy Bypass -File C:\Scripts\watch-iis.ps1"
# Every 5 minutes
$trigger = New-ScheduledTaskTrigger -Once -At (Get-Date) `
  -RepetitionInterval (New-TimeSpan -Minutes 5) `
  -RepetitionDuration ([TimeSpan]::MaxValue)
Register-ScheduledTask -TaskName "Watch IIS" `
  -Action $action -Trigger $trigger -User "SYSTEM" -RunLevel Highest

Manage Existing Tasks

# List all tasks
Get-ScheduledTask

# Filter by state
Get-ScheduledTask | Where-Object State -eq "Disabled"
Get-ScheduledTask | Where-Object State -eq "Ready"

# Run task manually
Start-ScheduledTask -TaskName "Nightly Backup"

# Enable / Disable
Enable-ScheduledTask -TaskName "Nightly Backup"
Disable-ScheduledTask -TaskName "Nightly Backup"

# Delete task
Unregister-ScheduledTask -TaskName "Nightly Backup" -Confirm:$false

# View last result
(Get-ScheduledTaskInfo -TaskName "Nightly Backup").LastTaskResult
# 0 = success, any other value = error

PowerShell Execution Permissions

If PowerShell scripts don't run, check execution policy:

# View current policy
Get-ExecutionPolicy -List

# Enable signed or local scripts for system
Set-ExecutionPolicy RemoteSigned -Scope LocalMachine

# Or, for task only, use -ExecutionPolicy Bypass flag in action

Logs and Debug

# View task execution history (last 10 runs)
Get-ScheduledTaskInfo -TaskName "Nightly Backup"

# Detailed log in Event Viewer
# Event Viewer → Applications and Services Logs
#           → Microsoft → Windows → TaskScheduler → Operational

# Enable operational log if disabled
wevtutil set-log "Microsoft-Windows-TaskScheduler/Operational" /enabled:true

Common Error Codes

0x1: script not found or generic error. 0x41301: task still running (timeout). 0x8007010B: directory not found. Always check absolute path of scripts.

On this page