Test-sthWindowsUpdateRebootRequired.ps1

<#
.synopsis
Function for testing and rebooting computers on reboot pending after update installation
 
.description
Function for testing local and remote computers on reboot pending after update installation.
 
Checks Component Based Servicing registry key - HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Component Based Servicing\RebootPending
and Windows Update registry key - HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\WindowsUpdate\Auto Update\RebootRequired.
 
Also have the possibility to initiate reboot on remote computers (not local) which need it by specifying -Restart and -YesRestart parameters.
Does not initiate reboot on local computer (can be specified as 'localhost', 'hostname' or 'hostname.domainname.com')
 
By default function skips computers, that can not be accessed.
You can see, which computers were skipped by specifying -ShowInaccessible.
 
.example
Test-sthWindowsUpdateRebootRequired
 
ComputerName ComponentBasedServicing WindowsUpdate
------------ ----------------------- -------------
localhost False False
 
Get information about localhost.
 
.example
Test-sthWindowsUpdateRebootRequired -ComputerName comp-1, comp-2, localhost
 
ComputerName ComponentBasedServicing WindowsUpdate
------------ ----------------------- -------------
comp-1 False False
comp-2 True True
localhost False False
 
Get information from several computers by specifying -ComputerName parameter.
 
.example
'comp-1', 'comp-2', 'localhost' | Test-sthWindowsUpdateRebootRequired
 
ComputerName ComponentBasedServicing WindowsUpdate
------------ ----------------------- -------------
comp-1 False False
comp-2 True True
localhost False False
 
Get information from several computers by piping names of the computers into the function.
 
.example
 
Test-sthWindowsUpdateRebootRequired -ComputerName comp-1,comp-2,localhost,Inaccessiblecomputer -ShowInaccessible
 
ComputerName ComponentBasedServicing WindowsUpdate
------------ ----------------------- -------------
comp-1 False False
comp-2 True True
Inaccessiblecomputer Inaccessible Inaccessible False False
 
Get information from several computers by specifying -ComputerName.
Also get information about inaccessible computers by specifying -Inaccessible parameter.
 
(By default inaccessible computers is silently skipped.)
 
.example
Test-sthWindowsUpdateRebootRequired -ComputerName comp-1,comp-2,localhost -Restart -YesRestart
 
ComputerName ComponentBasedServicing WindowsUpdate
------------ ----------------------- -------------
comp-1 False False
comp-2 True True
localhost True True
 
Get information from several computers and restart computers that needs it. (does not restarts localhost)
In this example comp-2 will be restarted.
 
(Both -Restart and -YesRestart parameters must be specified.)
#>


function Test-sthWindowsUpdateRebootRequired
{
    [CmdletBinding()]
    Param(
        #Computer Name.
        #By default = 'localhost'
        [Parameter(ValueFromPipeline=$True)]
        [string[]]$ComputerName = 'localhost',
        #Restart computers which need it (remote only)
        [switch]$Restart,
        #Explicit reboot confirmation
        [switch]$YesRestart,
        #Show inaccessible computers in results
        [switch]$ShowInaccessible
    )
    
    begin
    {
        $Inaccessible = @()
        $WMI = Get-WmiObject -Class Win32_ComputerSystem
        $Name = $WMI.Name
        $Domain = $WMI.Domain
    }

    process
    {
        foreach ($c in $ComputerName)
        {
            Write-Progress -Activity "Testing computers" -CurrentOperation $c
            
            if(($c -eq 'localhost') -or ($c -eq $Name) -or ($c -eq $($Name, $Domain -join '.')))
            {
                $CBS = Test-Path 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Component Based Servicing\RebootPending'
                $WU = Test-Path 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\WindowsUpdate\Auto Update\RebootRequired'
            }

            else
            {
                if($sess = New-PSSession -ComputerName $c -ErrorAction SilentlyContinue)
                {
                    $CBS = Invoke-Command -ScriptBlock {Test-Path 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Component Based Servicing\RebootPending'} -Session $sess
                    $WU = Invoke-Command -ScriptBlock {Test-Path 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\WindowsUpdate\Auto Update\RebootRequired'} -Session $sess

                    if($Restart -and $YesRestart -and ($CBS -or $WU))
                    {
                        Invoke-Command -ScriptBlock {Restart-Computer -Force} -Session $sess
                    }
                    
                    Remove-PSSession -Session $sess
                }
                else
                {
                    $Inaccessible += $c
                    continue
                }
            }
            New-Object -TypeName PSCustomObject -Property $([ordered]@{
                ComputerName = $c
                ComponentBasedServicing = $CBS
                WindowsUpdate = $WU
            })
        }
    }

    end
    {
        if($ShowInaccessible)
        {
            foreach($i in $Inaccessible)
            {
                New-Object -TypeName PSCustomObject -Property $([ordered]@{
                ComputerName = $i
                ComponentBasedServicing = 'Inaccessible'
                WindowsUpdate = 'Inaccessible'
                })
            }
        }
    }
}