Public/system/Get-PendingReboot.ps1
|
#Requires -Version 5.1 function Get-PendingReboot { <# .SYNOPSIS Checks pending reboot status from multiple Windows sources .DESCRIPTION Queries multiple system sources to determine if a Windows machine has a pending reboot. Sources include Component Based Servicing, Windows Update, pending file rename operations, pending computer rename, and SCCM client SDK. .PARAMETER ComputerName One or more computer names to check. Defaults to the local machine name. Accepts pipeline input by value and by property name. .PARAMETER Credential Optional PSCredential object for authenticating to remote machines. Not used for local machine checks. .EXAMPLE Get-PendingReboot Checks the local machine for any pending reboot indicators. .EXAMPLE Get-PendingReboot -ComputerName 'SERVER01' Checks a single remote machine for pending reboot status. .EXAMPLE 'SERVER01', 'SERVER02' | Get-PendingReboot -Credential (Get-Credential) Checks multiple remote machines via pipeline input with alternate credentials. .NOTES Author: Franck SALLET Version: 1.0.0 Last Modified: 2026-03-18 Requires: PowerShell 5.1+ / Windows only Permissions: Some checks may require administrative privileges. Remote checks require WinRM to be enabled on target machines. SCCM checks require the ConfigMgr client to be installed. Local computer name detection covers $env:COMPUTERNAME, 'localhost', and '.'. FQDN or IP of the local machine will be treated as a remote target. #> [CmdletBinding()] [OutputType([PSCustomObject])] param( [Parameter(ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true)] [ValidateNotNullOrEmpty()] [string[]]$ComputerName = $env:COMPUTERNAME, [Parameter()] [System.Management.Automation.PSCredential] [System.Management.Automation.Credential()] $Credential ) begin { Write-Verbose "[$($MyInvocation.MyCommand)] Starting pending reboot check" $localNames = @($env:COMPUTERNAME, 'localhost', '.') $checkScript = { $cbsPath = 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Component Based Servicing\RebootPending' $wuPath = 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\WindowsUpdate\Auto Update\RebootRequired' $smPath = 'HKLM:\SYSTEM\CurrentControlSet\Control\Session Manager' $activeNamePath = 'HKLM:\SYSTEM\CurrentControlSet\Control\ComputerName\ActiveComputerName' $pendingNamePath = 'HKLM:\SYSTEM\CurrentControlSet\Control\ComputerName\ComputerName' $componentBasedServicing = Test-Path -Path $cbsPath $windowsUpdate = Test-Path -Path $wuPath $pfroValue = (Get-ItemProperty -Path $smPath -Name 'PendingFileRenameOperations' -ErrorAction SilentlyContinue).PendingFileRenameOperations $pendingFileRename = ($null -ne $pfroValue) -and (@($pfroValue).Count -gt 0) $activeName = (Get-ItemProperty -Path $activeNamePath -Name 'ComputerName' -ErrorAction SilentlyContinue).ComputerName $pendingName = (Get-ItemProperty -Path $pendingNamePath -Name 'ComputerName' -ErrorAction SilentlyContinue).ComputerName $pendingComputerRename = $activeName -ne $pendingName $ccmClientSDK = $null try { $ccmResult = Invoke-CimMethod -Namespace 'ROOT\ccm\ClientSDK' -ClassName 'CCM_ClientUtilities' -MethodName 'DetermineIfRebootPending' -ErrorAction Stop $ccmClientSDK = [bool]($ccmResult.IsHardRebootPending -or $ccmResult.RebootPending) } catch { $ccmClientSDK = $null } @{ ComponentBasedServicing = $componentBasedServicing WindowsUpdate = $windowsUpdate PendingFileRename = $pendingFileRename PendingComputerRename = $pendingComputerRename CCMClientSDK = $ccmClientSDK } } } process { foreach ($computer in $ComputerName) { Write-Verbose "[$($MyInvocation.MyCommand)] Checking pending reboot on '$computer'" try { $isLocal = $localNames -contains $computer if ($isLocal) { $checkResult = & $checkScript } else { $invokeParams = @{ ComputerName = $computer ScriptBlock = $checkScript ErrorAction = 'Stop' } if ($PSBoundParameters.ContainsKey('Credential')) { $invokeParams['Credential'] = $Credential } $checkResult = Invoke-Command @invokeParams } $isRebootPending = ( $checkResult['ComponentBasedServicing'] -or $checkResult['WindowsUpdate'] -or $checkResult['PendingFileRename'] -or $checkResult['PendingComputerRename'] -or ($checkResult['CCMClientSDK'] -eq $true) ) [PSCustomObject]@{ PSTypeName = 'PSWinOps.PendingReboot' ComputerName = $computer IsRebootPending = [bool]$isRebootPending ComponentBasedServicing = [bool]$checkResult['ComponentBasedServicing'] WindowsUpdate = [bool]$checkResult['WindowsUpdate'] PendingFileRename = [bool]$checkResult['PendingFileRename'] PendingComputerRename = [bool]$checkResult['PendingComputerRename'] CCMClientSDK = $checkResult['CCMClientSDK'] Timestamp = (Get-Date -Format 'o') } } catch { Write-Error "[$($MyInvocation.MyCommand)] Failed to check pending reboot on '$computer': $_" } } } end { Write-Verbose "[$($MyInvocation.MyCommand)] Completed pending reboot check" } } |