Reboot Pending Script

Checks the standard Windows pending-reboot signals: Component Based Servicing, Windows Update, pending file rename operations, and pending computer rename. Returns exit code 1 when a reboot is pending and the device has been up longer than the minimum uptime threshold, triggering the paired remediation that schedules a restart with user warning.

Remediation
2.2k views836 downloadsVersion 1.0By Ugur Koc
View on GitHub

// QUALITY CHECKS

Validation status

Quality checks

All checks pass
  • ParsePass
  • LintPass
  • MetadataPass
  • Runbook-readyPass
  • Module depsPass

Tests run automatically on every change. What does each check mean?

// REQUIRED PERMISSIONS

Microsoft Graph scopes

DeviceManagementManagedDevices.ReadWrite.All

Allows the app to read and write the properties of devices managed by Microsoft Intune, without a signed-in user. Does not allow high impact operations such as remote wipe and password reset on the device's owner

// CHANGELOG

Version history

  1. Entry · 01

    1.0 - Initial release

// CODE

Source

reboot-pending.ps1
<#
.TITLE
    Reboot Pending Detection Script

.SYNOPSIS
    Detects devices that have a pending reboot older than the configured threshold.

.DESCRIPTION
    Checks the standard Windows pending-reboot signals: Component Based Servicing,
    Windows Update, pending file rename operations, and pending computer rename.
    Returns exit code 1 when a reboot is pending and the device has been up longer
    than the minimum uptime threshold, triggering the paired remediation that
    schedules a restart with user warning.

.TAGS
    Remediation,Detection

.REMEDIATIONTYPE
    Detection

.PAIRSCRIPT
    remediate-reboot-pending.ps1

.PLATFORM
    Windows

.MINROLE
    Intune Service Administrator

.PERMISSIONS
    DeviceManagementManagedDevices.ReadWrite.All

.AUTHOR
    Ugur Koc

.VERSION
    1.0

.CHANGELOG
    1.0 - Initial release

.LASTUPDATE
    2026-07-20

.EXAMPLE
    .\detect-reboot-pending.ps1
    Returns exit 1 if a reboot is pending and uptime exceeds the threshold

.NOTES
    - Runs in SYSTEM context via Intune Remediations
    - $MinimumUptimeDays avoids flagging devices that rebooted recently but picked up a new pending flag
    - PendingFileRenameOperations alone is noisy (installers set it constantly), so it only counts together with uptime
#>

$ErrorActionPreference = "Stop"

# Only flag devices that have not rebooted for at least this long
$MinimumUptimeDays = 2

function Test-PendingReboot {
    $reasons = [System.Collections.Generic.List[string]]::new()

    if (Test-Path "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Component Based Servicing\RebootPending") {
        $reasons.Add("Component Based Servicing")
    }

    if (Test-Path "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\WindowsUpdate\Auto Update\RebootRequired") {
        $reasons.Add("Windows Update")
    }

    try {
        $pendingRenames = (Get-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Control\Session Manager" -Name PendingFileRenameOperations -ErrorAction SilentlyContinue).PendingFileRenameOperations
        if ($pendingRenames) {
            $reasons.Add("Pending file rename operations")
        }
    }
    catch {
        # Value not present - nothing pending
    }

    try {
        $activeName = (Get-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Control\ComputerName\ActiveComputerName" -Name ComputerName -ErrorAction SilentlyContinue).ComputerName
        $pendingName = (Get-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Control\ComputerName\ComputerName" -Name ComputerName -ErrorAction SilentlyContinue).ComputerName
        if ($activeName -and $pendingName -and $activeName -ne $pendingName) {
            $reasons.Add("Pending computer rename ($activeName -> $pendingName)")
        }
    }
    catch {
        # Ignore - rename detection is best effort
    }

    return @($reasons)
}

try {
    $lastBoot = (Get-CimInstance -ClassName Win32_OperatingSystem).LastBootUpTime
    $uptimeDays = [math]::Round(((Get-Date) - $lastBoot).TotalDays, 1)

    $pendingReasons = Test-PendingReboot

    if ($pendingReasons.Count -eq 0) {
        Write-Output "No reboot pending. Uptime: $uptimeDays days."
        exit 0
    }

    if ($uptimeDays -lt $MinimumUptimeDays) {
        Write-Output "Reboot pending ($($pendingReasons -join '; ')) but uptime is only $uptimeDays days - below the $MinimumUptimeDays day threshold."
        exit 0
    }

    Write-Output "Reboot pending for $uptimeDays days: $($pendingReasons -join '; ')"
    exit 1
}
catch {
    Write-Error $_
    exit 2
}

// NOTES

Author notes

- Runs in SYSTEM context via Intune Remediations - $MinimumUptimeDays avoids flagging devices that rebooted recently but picked up a new pending flag - PendingFileRenameOperations alone is noisy (installers set it constantly), so it only counts together with uptime

// RELATED

Picked by shared tags, category, and script type — nothing magic, just metadata overlap.

  1. Windows Defender Definition Update

    Checks if Windows Defender definitions are current (within 48 hours). Returns exit code 1 if definitions are outdated.

    Remediation
  2. Disk Cleanup Script

    Checks Windows temp folders and recycle bin size. Returns exit code 1 if more than 1GB can be cleaned up.

    Remediation
  3. Local Admin Drift Script

    Enumerates the local Administrators group and compares every member against an allowlist of approved accounts and well-known SIDs (built-in Administrator, the Entra-joined device admin roles, and configurable extra entries). Returns exit code 1 when unauthorized members are present, triggering the paired remediation that removes them. This catches technician accounts, self-elevation leftovers, and helpdesk additions that were never cleaned up.

    Remediation