Advertisement
Yevrag35

GetPendingReboot

Jul 31st, 2019
842
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. <#
  2. .SYNOPSIS
  3.     Gets the pending reboot status on a local or remote computer.
  4.  
  5. .DESCRIPTION
  6.     This function will query the registry on a local or remote computer and determine if the
  7.     system is pending a reboot, from Microsoft updates, Configuration Manager Client SDK, Pending Computer
  8.     Rename, Domain Join or Pending File Rename Operations. For Windows 2008+ the function will query the
  9.     CBS registry key as another factor in determining pending reboot state.  "PendingFileRenameOperations"
  10.     and "Auto Update\RebootRequired" are observed as being consistant across Windows Server 2003 & 2008.
  11.    
  12.     CBServicing = Component Based Servicing (Windows 2008+)
  13.     WindowsUpdate = Windows Update / Auto Update (Windows 2003+)
  14.     CCMClientSDK = SCCM 2012 Clients only (DetermineIfRebootPending method) otherwise $null value
  15.     PendComputerRename = Detects either a computer rename or domain join operation (Windows 2003+)
  16.     PendFileRename = PendingFileRenameOperations (Windows 2003+)
  17.     PendFileRenVal = PendingFilerenameOperations registry value; used to filter if need be, some Anti-
  18.                      Virus leverage this key for def/dat removal, giving a false positive PendingReboot
  19.  
  20. .PARAMETER ComputerName
  21.     A single Computer or an array of computer names.  The default is localhost ($env:COMPUTERNAME).
  22.  
  23. .PARAMETER ErrorLog
  24.     A single path to send error data to a log file.
  25.  
  26. .EXAMPLE
  27.     PS C:\> Get-PendingReboot -ComputerName (Get-Content C:\ServerList.txt) | Format-Table -AutoSize
  28.    
  29.     Computer CBServicing WindowsUpdate CCMClientSDK PendFileRename PendFileRenVal RebootPending
  30.     -------- ----------- ------------- ------------ -------------- -------------- -------------
  31.     DC01           False         False                       False                        False
  32.     DC02           False         False                       False                        False
  33.     FS01           False         False                       False                        False
  34.  
  35.     This example will capture the contents of C:\ServerList.txt and query the pending reboot
  36.     information from the systems contained in the file and display the output in a table. The
  37.     null values are by design, since these systems do not have the SCCM 2012 client installed,
  38.     nor was the PendingFileRenameOperations value populated.
  39.  
  40. .EXAMPLE
  41.     PS C:\> Get-PendingReboot
  42.    
  43.     Computer           : WKS01
  44.     CBServicing        : False
  45.     WindowsUpdate      : True
  46.     CCMClient          : False
  47.     PendComputerRename : False
  48.     PendFileRename     : False
  49.     PendFileRenVal     :
  50.     RebootPending      : True
  51.    
  52.     This example will query the local machine for pending reboot information.
  53.    
  54. .EXAMPLE
  55.     PS C:\> $Servers = Get-Content C:\Servers.txt
  56.     PS C:\> Get-PendingReboot -Computer $Servers | Export-Csv C:\PendingRebootReport.csv -NoTypeInformation
  57.    
  58.     This example will create a report that contains pending reboot information.
  59.  
  60. .LINK
  61.     Component-Based Servicing:
  62.     http://technet.microsoft.com/en-us/library/cc756291(v=WS.10).aspx
  63.    
  64.     PendingFileRename/Auto Update:
  65.     http://support.microsoft.com/kb/2723674
  66.     http://technet.microsoft.com/en-us/library/cc960241.aspx
  67.     http://blogs.msdn.com/b/hansr/archive/2006/02/17/patchreboot.aspx
  68.  
  69.     SCCM 2012/CCM_ClientSDK:
  70.     http://msdn.microsoft.com/en-us/library/jj902723.aspx
  71.  
  72. .NOTES
  73.     Author:  Brian Wilhite
  74.     Email:   bcwilhite (at) live.com
  75.     Date:    29AUG2012
  76.     PSVer:   2.0/3.0/4.0/5.0
  77.     Updated: 27JUL2015
  78.     UpdNote: Added Domain Join detection to PendComputerRename, does not detect Workgroup Join/Change
  79.              Fixed Bug where a computer rename was not detected in 2008 R2 and above if a domain join occurred at the same time.
  80.              Fixed Bug where the CBServicing wasn't detected on Windows 10 and/or Windows Server Technical Preview (2016)
  81.              Added CCMClient property - Used with SCCM 2012 Clients only
  82.              Added ValueFromPipelineByPropertyName=$true to the ComputerName Parameter
  83.              Removed $Data variable from the PSObject - it is not needed
  84.              Bug with the way CCMClientSDK returned null value if it was false
  85.              Removed unneeded variables
  86.              Added PendFileRenVal - Contents of the PendingFileRenameOperations Reg Entry
  87.              Removed .Net Registry connection, replaced with WMI StdRegProv
  88.              Added ComputerPendingRename
  89. #>
  90. #Requires -Version 3.0
  91. [CmdletBinding()]
  92. param
  93. (
  94.     [Parameter(Position=0,ValueFromPipeline=$true,ValueFromPipelineByPropertyName=$true)]
  95.     [Alias("CN","Computer")]
  96.     [String]$ComputerName="$env:COMPUTERNAME"
  97.     ,
  98.     [String]$ErrorLog
  99. )
  100. Process
  101. {
  102.     Try
  103.     {
  104.         ## Setting pending values to false to cut down on the number of else statements
  105.         $CompPendRen,$PendFileRename,$Pending,$SCCM = $false,$false,$false,$false
  106.                        
  107.         ## Setting CBSRebootPend to null since not all versions of Windows has this value
  108.         $CBSRebootPend = $null
  109.                        
  110.         ## Querying WMI for build version
  111.         $WMI_OS = Get-WmiObject -Class Win32_OperatingSystem -Property BuildNumber, CSName -ComputerName $ComputerName -ErrorAction Stop
  112.  
  113.         ## Making registry connection to the local/remote computer
  114.         $HKLM = [UInt32] "0x80000002"
  115.         $WMI_Reg = [WMIClass] "\\$ComputerName\root\default:StdRegProv"
  116.                        
  117.         ## If Vista/2008 & Above query the CBS Reg Key
  118.         If ([Int32]$WMI_OS.BuildNumber -ge 6001)
  119.         {
  120.             $RegSubKeysCBS = $WMI_Reg.EnumKey($HKLM,"SOFTWARE\Microsoft\Windows\CurrentVersion\Component Based Servicing\")
  121.             $CBSRebootPend = $RegSubKeysCBS.sNames -contains "RebootPending"       
  122.         }
  123.                            
  124.         ## Query WUAU from the registry
  125.         $RegWUAURebootReq = $WMI_Reg.EnumKey($HKLM,"SOFTWARE\Microsoft\Windows\CurrentVersion\WindowsUpdate\Auto Update\")
  126.         $WUAURebootReq = $RegWUAURebootReq.sNames -contains "RebootRequired"
  127.                        
  128.         ## Query PendingFileRenameOperations from the registry
  129.         $RegSubKeySM = $WMI_Reg.GetMultiStringValue($HKLM,"SYSTEM\CurrentControlSet\Control\Session Manager\","PendingFileRenameOperations")
  130.         $RegValuePFRO = $RegSubKeySM.sValue
  131.  
  132.         ## Query JoinDomain key from the registry - These keys are present if pending a reboot from a domain join operation
  133.         $Netlogon = $WMI_Reg.EnumKey($HKLM,"SYSTEM\CurrentControlSet\Services\Netlogon").sNames
  134.         $PendDomJoin = ($Netlogon -contains 'JoinDomain') -or ($Netlogon -contains 'AvoidSpnSet')
  135.  
  136.         ## Query ComputerName and ActiveComputerName from the registry
  137.         $ActCompNm = $WMI_Reg.GetStringValue($HKLM,"SYSTEM\CurrentControlSet\Control\ComputerName\ActiveComputerName\","ComputerName")            
  138.         $CompNm = $WMI_Reg.GetStringValue($HKLM,"SYSTEM\CurrentControlSet\Control\ComputerName\ComputerName\","ComputerName")
  139.  
  140.         If (($ActCompNm -ne $CompNm) -or $PendDomJoin)
  141.         {
  142.             $CompPendRen = $true
  143.         }
  144.                        
  145.         ## If PendingFileRenameOperations has a value set $RegValuePFRO variable to $true
  146.         If ($RegValuePFRO)
  147.         {
  148.             $PendFileRename = $true
  149.         }
  150.  
  151.         ## Determine SCCM 2012 Client Reboot Pending Status
  152.         ## To avoid nested 'if' statements and unneeded WMI calls to determine if the CCM_ClientUtilities class exist, setting EA = 0
  153.         $CCMClientSDK = $null
  154.         $CCMSplat = @{
  155.             NameSpace='ROOT\ccm\ClientSDK'
  156.             Class='CCM_ClientUtilities'
  157.             Name='DetermineIfRebootPending'
  158.             ComputerName=$ComputerName
  159.             ErrorAction='Stop'
  160.         }
  161.         ## Try CCMClientSDK
  162.         Try
  163.         {
  164.             $CCMClientSDK = Invoke-WmiMethod @CCMSplat
  165.         }
  166.         Catch [System.UnauthorizedAccessException]
  167.         {
  168.             $CcmStatus = Get-Service -Name CcmExec -ComputerName $ComputerName -ErrorAction SilentlyContinue
  169.             If ($CcmStatus.Status -ne 'Running')
  170.             {
  171.                 Write-Warning "$ComputerName`: Error - CcmExec service is not running."
  172.                 $CCMClientSDK = $null
  173.             }
  174.         }
  175.         Catch
  176.         {
  177.             $CCMClientSDK = $null
  178.         }
  179.  
  180.         If ($CCMClientSDK)
  181.         {
  182.             If ($CCMClientSDK.ReturnValue -ne 0)
  183.             {
  184.                 Write-Warning "Error: DetermineIfRebootPending returned error code $($CCMClientSDK.ReturnValue)"          
  185.             }
  186.             If ($CCMClientSDK.IsHardRebootPending -or $CCMClientSDK.RebootPending)
  187.             {
  188.                 $SCCM = $true
  189.             }
  190.         }
  191.         Else
  192.         {
  193.             $SCCM = $null
  194.         }
  195.        
  196.         ## Creating Custom PSObject and Select-Object Splat
  197.         $SelectSplat = @{
  198.             Property=(
  199.                 'Computer',
  200.                 'CBServicing',
  201.                 'WindowsUpdate',
  202.                 'CCMClientSDK',
  203.                 'PendComputerRename',
  204.                 'PendFileRename',
  205.                 'PendFileRenVal',
  206.                 'RebootPending'
  207.             )}
  208.         Write-Verbose $(New-Object -TypeName PSObject -Property @{
  209.             Computer=$WMI_OS.CSName
  210.             CBServicing=$CBSRebootPend
  211.             WindowsUpdate=$WUAURebootReq
  212.             CCMClientSDK=$SCCM
  213.             PendComputerRename=$CompPendRen
  214.             PendFileRename=$PendFileRename
  215.             PendFileRenVal=$RegValuePFRO
  216.             RebootPending=($CompPendRen -or $CBSRebootPend -or $WUAURebootReq -or $SCCM -or $PendFileRename)
  217.         } | Select-Object @SelectSplat | Out-String)
  218.  
  219.         if ($CBSRebootPend -or $WUAURebootReq -or $CompPendRen -or $SCCM)
  220.         {
  221.             return $true
  222.         }
  223.         else
  224.         {
  225.             return $false
  226.         }
  227.     }
  228.     Catch
  229.     {
  230.         Write-Warning "$ComputerName`: $_"
  231.         ## If $ErrorLog, log the file to a user specified location/path
  232.         If ($ErrorLog)
  233.         {
  234.             Out-File -InputObject "$ComputerName`,$_" -FilePath $ErrorLog -Append
  235.         }
  236.     }
  237.  
  238. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement