Windows Server 2016 Scheduled Task Bug: Past Start Times Prevent Execution After Reboot – Workarounds and Solutions


1 views

When migrating from Windows Server 2012 to 2016, many administrators encounter this frustrating behavior: scheduled tasks with start times in the past simply refuse to execute. Unlike Server 2012 which would honor the recurrence pattern regardless of initial start time, Server 2016 requires the first run to be in the future.

Consider this common monitoring scenario:

$Action = New-ScheduledTaskAction -Execute "Powershell.exe" -Argument "C:\Monitoring\check_services.ps1"
$Trigger = New-ScheduledTaskTrigger -Once -At (Get-Date).Date -RepetitionInterval (New-TimeSpan -Minutes 5)
Register-ScheduledTask -TaskName "ServiceMonitor" -Action $Action -Trigger $Trigger

This works perfectly in 2012 but fails silently in 2016 after server reboots.

The most reliable solution is to create a one-time trigger that runs indefinitely:

$Trigger = New-ScheduledTaskTrigger -Once -At (Get-Date).AddMinutes(5) -RepetitionInterval (New-TimeSpan -Minutes 5)
$Settings = New-ScheduledTaskSettingsSet -StartWhenAvailable -DontStopOnIdleEnd
Register-ScheduledTask -TaskName "ServiceMonitor" -Action $Action -Trigger $Trigger -Settings $Settings

For non-regular intervals, consider these approaches:

  1. Task Wrapper Script:
    # check_last_run.ps1
    $lastRun = Get-Date -Date (Get-ScheduledTaskInfo -TaskName "MyTask").LastRunTime
    if ((New-TimeSpan -Start $lastRun -End (Get-Date)).TotalMinutes -ge 30) {
        & "C:\Path\To\ActualTask.ps1"
    }
  2. Trigger Combination:
    $Trigger1 = New-ScheduledTaskTrigger -AtStartup
    $Trigger2 = New-ScheduledTaskTrigger -Once -At (Get-Date).AddMinutes(5) -RepetitionInterval (New-TimeSpan -Minutes 5)
    Register-ScheduledTask -TaskName "HybridTask" -Action $Action -Trigger @($Trigger1,$Trigger2)

Microsoft has acknowledged this behavior in KB articles, though no official fix exists. Some administrators have had success with:

reg add "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Schedule\Configuration" /v "AllowPastStartTime" /t REG_DWORD /d 1 /f

Note: This undocumented setting may not work in all environments.

After implementing any solution, verify with:

Get-ScheduledTask | Where-Object {$_.State -ne "Ready"} | Format-Table -AutoSize
Get-ScheduledTaskInfo -TaskName "YourTask" | Select-Object LastRunTime,NextRunTime,LastTaskResult

When migrating scheduled tasks from Windows Server 2012 R2 to 2016, many administrators encounter a critical behavioral change: tasks configured with start times in the past simply won't execute. This creates particular challenges for:

  • Recurring monitoring tasks (e.g., every 3-5 minutes)
  • System maintenance scripts
  • Batch processing jobs

In Server 2012 R2, you could create a task like this (PowerShell example):

$Action = New-ScheduledTaskAction -Execute 'powershell.exe' -Argument '-File C:\monitoring\check_services.ps1'
$Trigger = New-ScheduledTaskTrigger -Daily -At "12:00AM" -RepetitionInterval (New-TimeSpan -Minutes 5)
Register-ScheduledTask -TaskName "ServiceMonitor" -Action $Action -Trigger $Trigger

This would immediately begin executing every 5 minutes. Server 2016 ignores such configurations completely.

The most reliable solution we've found involves creating a "One Time" trigger with indefinite repetition:

$Trigger = New-ScheduledTaskTrigger -Once -At (Get-Date).AddMinutes(1) -RepetitionInterval (New-TimeSpan -Minutes 5)

Key advantages:

  • Survives server reboots
  • Doesn't require multiple triggers
  • Maintains predictable execution intervals

For more complex scheduling needs, consider these approaches:

1. Wrapper Script Method

# File: task_wrapper.ps1
while ($true) {
    & C:\scripts\actual_task.ps1
    Start-Sleep -Seconds 300 # 5 minute interval
}

2. Event-Based Triggering

$Trigger = New-ScheduledTaskTrigger -AtStartup
$Settings = New-ScheduledTaskSettingsSet -StartWhenAvailable -DontStopOnIdleEnd

While not officially documented, some administrators report success with these registry modifications:

Windows Registry Editor Version 5.00

[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Schedule\TaskCache\Tree]
"BypassPastStartTimeCheck"=dword:00000001

Use with caution and thoroughly test in non-production environments first.

Implement robust monitoring since failed tasks won't appear in task history:

# PowerShell monitoring script example
$Tasks = Get-ScheduledTask | Where-Object { $_.State -eq "Ready" -and $_.NextRunTime -lt (Get-Date).AddMinutes(-10) }
if ($Tasks) {
    Send-MailMessage -To "admin@domain.com" -Subject "Stuck Tasks Alert" -Body ($Tasks | Out-String)
}