Skip to content
Get started

How to monitor a Windows Task Scheduler task

To monitor a Windows Task Scheduler task, use Get-ScheduledTaskInfo in PowerShell to check the last run result and last run time. A LastTaskResult of 0x0 is success; a result beginning with 0x8004 is a SCHED_E_ error. SCHED_S_TASK_HAS_NOT_RUN (0x00041303) means the task hasn't run yet; SCHED_S_TASK_NO_VALID_TRIGGERS (0x00041307) means no trigger will ever fire. For continuous alerting, add a heartbeat from inside the task's action and alert when the expected ping doesn't arrive.

How do I check the last run result with PowerShell?

PowerShell — check task health
# Get the last run time and result for a specific task.
$info = Get-ScheduledTaskInfo -TaskName "NightlyReport"
$info | Select-Object LastRunTime, LastTaskResult, NextRunTime

# LastTaskResult 0 = success (SCHED_S_TASK_READY)
# LastTaskResult 0x00041303 = has not run yet
# LastTaskResult 0x00041307 = no valid triggers
# LastTaskResult 0x8004xxxx = SCHED_E_ error (the task failed)

You can poll this in a scheduled PowerShell script and send an alert when LastTaskResult is non-zero or when LastRunTime is older than expected:

$info = Get-ScheduledTaskInfo -TaskName "NightlyReport"
$maxAge = (Get-Date).AddHours(-25)

if ($info.LastTaskResult -ne 0) {
    Write-Host "Task failed with code: $($info.LastTaskResult)"
    # Send alert here (email, webhook, etc.)
} elseif ($info.LastRunTime -lt $maxAge) {
    Write-Host "Task has not run in over 25 hours"
    # Send alert here
}

How do I enable Task Scheduler history?

Task history is disabled by default. Enable it before you start monitoring — without it, the History tab is empty and Get-ScheduledTaskInfo has no event data to draw from:

# Enable all tasks history (requires administrator privileges).
$logName = "Microsoft-Windows-TaskScheduler/Operational"
$log = New-Object System.Diagnostics.Eventing.Reader.EventLogConfiguration $logName
$log.IsEnabled = $true
$log.SaveChanges()

How do I add a heartbeat from a Task Scheduler action?

Task action script (nightly-report.ps1)
# Set strict mode so any error terminates the script.
Set-StrictMode -Version Latest
$ErrorActionPreference = "Stop"

# Do the work.
Invoke-YourNightlyJob

# Report success last — only reached if no error above.
Invoke-WebRequest -Uri "https://ping.cronshield.com/<your-check-id>" -UseBasicParsing -TimeoutSec 10
PING_URL is a placeholder for the endpoint you get when you create a monitor. The CronShield receiver ships in an upcoming release. $ErrorActionPreference = 'Stop' ensures any PowerShell error terminates the script before the ping fires.

Add a missed-run alert to this job

The free tier gives you a heartbeat endpoint and an email alert when an expected ping doesn't arrive. Paid tiers add the log-aware diagnosis — the last log line and a likely cause in the alert. The heartbeat receiver ships in an upcoming release; see the plans to learn what each tier adds.

Frequently asked questions

What does SCHED_E_TASK_ATTEMPTED (0x80041324) mean?
SCHED_E_TASK_ATTEMPTED means Task Scheduler tried to run the task but it did not run due to a constraint in the task definition — for example a required network condition was not met, a user was not logged in, or the task was configured to stop if the computer switches to battery power.
Why does Get-ScheduledTaskInfo show LastRunTime as the initial date?
If the task has never run, LastRunTime shows 11/30/1999 (a sentinel value) and LastTaskResult is 0x00041303 (SCHED_S_TASK_HAS_NOT_RUN). Check that the task is enabled and that at least one trigger has a valid future time.