Public/Get-EFPendingReboot.ps1
|
function Get-EFPendingReboot { <# .SYNOPSIS Determines whether Windows reports a pending restart. .DESCRIPTION Checks servicing, Windows Update, file rename, installer, and computer rename indicators. The command is read-only and returns the individual reasons. .EXAMPLE $reboot = Get-EFPendingReboot if ($reboot.IsRebootPending) { $reboot.Reasons } #> [CmdletBinding()] param() $null = Test-EFWindows -Throw $errors = [Collections.Generic.List[string]]::new() $indicators = [ordered]@{ ComponentBasedServicing = $false WindowsUpdate = $false PendingFileRename = $false UpdateExeVolatile = $false PendingComputerRename = $false } $nativeRegistry = $null try { $nativeView = if ([Environment]::Is64BitOperatingSystem) { [Microsoft.Win32.RegistryView]::Registry64 } else { [Microsoft.Win32.RegistryView]::Registry32 } $nativeRegistry = [Microsoft.Win32.RegistryKey]::OpenBaseKey( [Microsoft.Win32.RegistryHive]::LocalMachine, $nativeView ) } catch { $errors.Add("NativeSoftwareRegistry: $($_.Exception.Message)") } foreach ($registryIndicator in @( @{ Name = 'ComponentBasedServicing'; Path = 'SOFTWARE\Microsoft\Windows\CurrentVersion\Component Based Servicing\RebootPending' }, @{ Name = 'WindowsUpdate'; Path = 'SOFTWARE\Microsoft\Windows\CurrentVersion\WindowsUpdate\Auto Update\RebootRequired' } )) { $indicatorKey = $null try { if ($null -eq $nativeRegistry) { continue } $indicatorKey = $nativeRegistry.OpenSubKey($registryIndicator.Path, $false) $indicators[$registryIndicator.Name] = $null -ne $indicatorKey } catch { $errors.Add("$($registryIndicator.Name): $($_.Exception.Message)") } finally { if ($null -ne $indicatorKey) { $indicatorKey.Dispose() } } } try { $sessionManager = Get-ItemProperty -LiteralPath 'HKLM:\SYSTEM\CurrentControlSet\Control\Session Manager' ` -Name PendingFileRenameOperations -ErrorAction Stop $indicators.PendingFileRename = @($sessionManager.PendingFileRenameOperations).Count -gt 0 } catch [System.Management.Automation.ItemNotFoundException] { Write-Verbose 'The pending file rename indicator is absent.' } catch [System.Management.Automation.PSArgumentException] { Write-Verbose 'The pending file rename indicator is absent.' } catch { $errors.Add("PendingFileRename: $($_.Exception.Message)") } $updatesKey = $null try { if ($null -ne $nativeRegistry) { $updatesKey = $nativeRegistry.OpenSubKey('SOFTWARE\Microsoft\Updates', $false) if ($null -ne $updatesKey) { $volatile = $updatesKey.GetValue( 'UpdateExeVolatile', $null, [Microsoft.Win32.RegistryValueOptions]::DoNotExpandEnvironmentNames ) if ($null -ne $volatile) { $indicators.UpdateExeVolatile = [int]$volatile -ne 0 } } } } catch { $errors.Add("UpdateExeVolatile: $($_.Exception.Message)") } finally { if ($null -ne $updatesKey) { $updatesKey.Dispose() } if ($null -ne $nativeRegistry) { $nativeRegistry.Dispose() } } try { $activeName = Get-ItemPropertyValue -LiteralPath 'HKLM:\SYSTEM\CurrentControlSet\Control\ComputerName\ActiveComputerName' -Name ComputerName -ErrorAction Stop $configuredName = Get-ItemPropertyValue -LiteralPath 'HKLM:\SYSTEM\CurrentControlSet\Control\ComputerName\ComputerName' -Name ComputerName -ErrorAction Stop if ([string]::IsNullOrWhiteSpace([string]$activeName) -or [string]::IsNullOrWhiteSpace([string]$configuredName)) { throw 'Windows returned an empty computer name.' } $indicators.PendingComputerRename = -not [string]::Equals($activeName, $configuredName, [StringComparison]::OrdinalIgnoreCase) } catch { $errors.Add("PendingComputerRename: $($_.Exception.Message)") } $reasons = @($indicators.GetEnumerator() | Where-Object Value | ForEach-Object Key) $reasonSummary = if ($reasons.Count -eq 0) { 'None' } else { $reasons -join ', ' } [pscustomobject]@{ PSTypeName = 'EndpointForge.PendingReboot' ComputerName = $env:COMPUTERNAME CheckedAtUtc = [DateTime]::UtcNow IsRebootPending = $reasons.Count -gt 0 DetectionCount = $reasons.Count DataStatus = if ($errors.Count -eq 0) { 'Complete' } else { 'Partial' } ErrorCount = $errors.Count Errors = @($errors) ReasonSummary = $reasonSummary Reasons = $reasons Indicators = [pscustomobject]$indicators } } |