Lately, I’ve been dealing with software installations on older Windows servers, and it has been quite frustrating. Many installers check for available resources and dependencies at the start but fail to verify if a reboot is pending. This oversight is frustrating because the installation proceeds, only to fail later solely due to the pending reboot, often after several steps, wasting time and effort. To avoid running into these failures unexpectedly, I created a PowerShell script that checks if a system reboot is required before proceeding with an installation.
The PowerShell Script
The script scans specific registry keys and values that Windows updates and other system processes use to indicate a pending reboot. These keys are commonly checked by installers and system administrators to determine if a restart is needed. The logic is based on information from Adam the Automator.
# Script to check if a system reboot is pending
# Based on details from: https://adamtheautomator.com/pending-reboot-registry/
# Variable to indicate if a reboot is pending
$PendingReboot = $false
# List of registry keys to check for a pending reboot
$RegKeysToCheck = @(
'HKLM:\SOFTWARE\Microsoft\ServerManager\CurrentRebootAttempts',
'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Component Based Servicing\PackagesPending',
'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Component Based Servicing\RebootInProgress',
'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Component Based Servicing\RebootPending',
'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\WindowsUpdate\Auto Update\PostRebootReporting',
'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\WindowsUpdate\Auto Update\RebootRequired'
)
# Iterate through the registry keys to check if they exist
foreach($RegKey in $RegKeysToCheck)
{
if(Test-Path -Path $RegKey)
{
Write-Output "$RegKey exists" # Print registry key if it exists
$PendingReboot = $true # Set flag to true if any key is found
}
}
# List of registry values to check for a pending reboot
$RegValuesToCheck = @(
@{ Path = 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\RunOnce'; Value = 'DVDRebootSignal' },
@{ Path = 'HKLM:\SYSTEM\CurrentControlSet\Control\Session Manager'; Value = 'PendingFileRenameOperations' },
@{ Path = 'HKLM:\SYSTEM\CurrentControlSet\Control\Session Manager'; Value = 'PendingFileRenameOperations2' },
@{ Path = 'HKLM:\SYSTEM\CurrentControlSet\Services\Netlogon'; Value = 'JoinDomain' },
@{ Path = 'HKLM:\SYSTEM\CurrentControlSet\Services\Netlogon'; Value = 'AvoidSpnSet' }
)
# Iterate through the registry values to check if they exist
foreach($RegValue in $RegValuesToCheck)
{
$property = Get-ItemProperty -Path $RegValue.Path -Name $RegValue.Value -ErrorAction SilentlyContinue
if($property)
{
Write-Output $RegValue.Path # Print the registry path if the value exists
$PendingReboot = $true # Set flag to true if any value is found
}
}
# Additional check for computer name mismatch
$ActiveComputerName = Get-ItemProperty -Path 'HKLM:\SYSTEM\CurrentControlSet\Control\ComputerName\ActiveComputerName' -ErrorAction SilentlyContinue | Select-Object -ExpandProperty ComputerName
$ComputerName = Get-ItemProperty -Path 'HKLM:\SYSTEM\CurrentControlSet\Control\ComputerName\ComputerName' -ErrorAction SilentlyContinue | Select-Object -ExpandProperty ComputerName
# If the active computer name differs from the stored name, a reboot is pending
if($ActiveComputerName -and $ComputerName -and ($ActiveComputerName -ne $ComputerName)) {
Write-Output "Computer name mismatch detected: $ActiveComputerName vs $ComputerName"
$PendingReboot = $true
}
# Check if there are any pending Windows Update services
'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\WindowsUpdate\Services\Pending' | Where-Object -FilterScript {
(Test-Path $_) -and (Get-ChildItem -Path $_)
} | ForEach-Object -Process { $PendingReboot = $true }
# Check for pending updates in Windows Updates
$PendingReboot = Get-ChildItem -Path 'HKLM:\SOFTWARE\Microsoft\Updates' -ErrorAction Ignore |
Where-Object -FilterScript { Test-Path -Path $_.PSPath -PathType Container } |
ForEach-Object -Process { (Get-ItemProperty -Path $_.PSPath -Name 'UpdateExeVolatile' -ErrorAction Ignore).UpdateExeVolatile -ne 0 }
# Output whether a reboot is pending
if ($PendingReboot) {
Write-Host "Reboot pending" -ForegroundColor Red
} else {
Write-Host "No reboot pending" -ForegroundColor Green
}
Conclusion
By checking for pending reboots in advance, you can prevent installation failures and reduce troubleshooting time. The script already covers various indicators of a pending reboot, such as Windows Update statuses, pending file rename operations, and domain join requirements, ensuring a comprehensive check. This script provides a simple yet effective way to ensure a smooth software installation process on Windows servers.