Check for pending reboot

Topics: Archive - Toolkit Extensions
Nov 26, 2014 at 9:29 AM
An option added to check for outstanding Pending Reboots would be nice.
Nov 28, 2014 at 6:29 PM
I finished this yesterday.
Still a work in progress because of the Windows Update test.
Function Get-PendingReboot {
<#
.SYNOPSIS
    Gets the pending reboot status on a local computer.
    
.DESCRIPTION
    Queries the registry and WMI to determine if the system waiting for a reboot, from:
        CBServicing   = Component Based Servicing (Windows 2008)
        WindowsUpdate = Windows Update / Auto Update (Windows 2003 / 2008)
        CCMClientSDK  = SCCM 2012 Clients only (DetermineIfRebootPending method) otherwise $null value
        PendFileRename = PendingFileRenameOperations (Windows 2003 / 2008)

.EXAMPLE
    Get-PendingReboot
    
.EXAMPLE
    Write-host "Need reboot =" $($ff.RebootPending)
    
.NOTES
    Based On: http://gallery.technet.microsoft.com/scriptcenter/Get-PendingReboot-Query-bdb79542
#>
    
    [String]$ComputerName="$env:COMPUTERNAME"
    $CBSRebootPend=$null
    $WUAURebootReq=$null
    $SCCM=$null
    $PendFileRename=$null
    $RegValuePFRO=$null
    $Pending=$null
    $LastBootUpTime=$null
    $PendRebootErrorMsg=$null
        
    Try {
        # Setting pending values to false to cut down on the number of else statements
        $PendFileRename,$Pending,$SCCM = $false,$false,$false
        
        # Setting CBSRebootPend to null since not all versions of Windows has this value
        $CBSRebootPend = $null
        
        # Querying WMI for build version
        $WMI_OS = Get-WmiObject -Class Win32_OperatingSystem -ComputerName $ComputerName
        $LastBootUpTime=$WMI_OS.ConvertToDateTime($WMI_OS.LastBootUpTime)
        
        # If Vista/2008 & Above query the CBS Reg Key
        If ($WMI_OS.BuildNumber -ge 6001) {
            If (Test-Path "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Component Based Servicing\RebootPending") {
            $CBSRebootPend=$true } else { $CBSRebootPend=$false }
        }#End If ($WMI_OS.BuildNumber -ge 6001)     
        
        #CAVEAT: this seems to be somewhat unreliable. The key also exists if Updates have not installed yet.
        #        A better test is needed 
        # Query WUAU from the registry
        If (Test-Path "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\WindowsUpdate\Auto Update") {
        $WUAURebootReq=$true } else { $WUAURebootReq=$false }
        
        # Query PendingFileRenameOperations from the registry
        $key="HKLM:\SYSTEM\CurrentControlSet\Control\Session Manager\"
        $Value="PendingFileRenameOperations"
        If (Test-Path "$key\$Value" -ErrorAction SilentlyContinue)  {
            $RegValuePFRO=Get-ItemProperty -Path $key | Select $Value -ExpandProperty $Value -ErrorAction SilentlyContinue
        } else { $RegValuePFRO=$null }

        # If PendingFileRenameOperations has a value set $RegValuePFRO variable to $true
        If ($RegValuePFRO) {
            $PendFileRename = $true
        } else {
#           $RegValuePFRO="<empty>"
            $PendFileRename = $false                
        }#End If ($RegValuePFRO)

        # Determine SCCM 2012 Client Reboot Pending Status
        # To avoid nested 'if' statements and unneeded WMI calls to determine if the CCM_ClientUtilities class exist, setting EA = 0
        $CCMClientSDK = $null
        $CCMSplat = @{
            NameSpace='ROOT\ccm\ClientSDK'
            Class='CCM_ClientUtilities'
            Name='DetermineIfRebootPending'
            ComputerName=$ComputerName
            ErrorAction='SilentlyContinue'
        }
        $CCMClientSDK = Invoke-WmiMethod @CCMSplat
        If ($CCMClientSDK) {
            If ($CCMClientSDK.ReturnValue -ne 0) {
                Write-Warning "Error: DetermineIfRebootPending returned error code $($CCMClientSDK.ReturnValue)"
            }#End If ($CCMClientSDK -and $CCMClientSDK.ReturnValue -ne 0)

            If ($CCMClientSDK.IsHardRebootPending -or $CCMClientSDK.RebootPending) {
                $SCCM = $true
            }#End If ($CCMClientSDK.IsHardRebootPending -or $CCMClientSDK.RebootPending)
        } #Else {
#           $SCCM = "N/A (sccm 2012 only)"
#        }                        
                        
    } Catch {
        Write-Warning "$ComputerName`: $_"
        $PendRebootErrorMsg=$_
    }#End Catch
    
    # If any of the variables are true, set $Pending variable to $true
    # If the variables are a mixture of false and Null, $Pending variable becomes $false
    If ($CBSRebootPend -or $WUAURebootReq -or $SCCM -or $PendFileRename) {
            $Pending = $true
    }#End If ($CBS -or $WUAU -or $PendFileRename)
        
    # Creating Custom PSObject and Select-Object Splat
    $SelectSplat = @{
        Property=('Computer','LastBootUpTime','CBServicing','WindowsUpdate','CCMClientSDK','PendFileRename','PendFileRenVal','RebootPending','ErrorMsg')
    }
    New-Object -TypeName PSObject -Property @{
        Computer=$WMI_OS.CSName
        CBServicing=$CBSRebootPend
        WindowsUpdate=$WUAURebootReq
        CCMClientSDK=$SCCM
        PendFileRename=$PendFileRename
        PendFileRenVal=$RegValuePFRO
        RebootPending=$Pending
        LastBootUpTime=$LastBootUpTime
        ErrorMsg=$PendRebootErrorMsg
    } | Select-Object @SelectSplat
            
}#Get-PendingReboot Function

Dec 10, 2014 at 5:08 PM
Edited Dec 10, 2014 at 5:21 PM
Nice work. For the Windows Update you just need to add the RebootRequired value: HKLM:SOFTWARE\Microsoft\Windows\CurrentVersion\WindowsUpdate\Auto Update\RebootRequired

The new xPendingReboot module has been released that is a part of the Windows PowerShell Desired State Configuration (DSC) Resource Kit. Download it and have a look at the code in the pms1 module. Some of it was also based on Brian Wilhite's code, the same as the article you referenced. It might give you some further ideas.

I was going to write a function too, but I'll leave that to you to complete :-)

Here's another example: http://billbjerrum.blogspot.com.au/2014/07/posh-script-to-return-compliancy-based.html

I'd like to also see this added to the OSD tasks in SCCM and MDT. Then you're not just adding a reboot for the sake of it. The client will only reboot when needed. A much more intelligent way of doing things!

Cheers,
Jeremy
Dec 31, 2014 at 11:21 PM
Edited Dec 31, 2014 at 11:22 PM
Hi,

What should be the best practices in a script by using your script? Do you have an up to date script?

Thanks,

François
Jan 13, 2015 at 10:02 PM
Here's an updated version.
I currently only use it for inventory/info purposes.
In the header in .EXAMPLE, I added 2 ways you could use it to act on the Pending Reboot status of the machine.
The key property to test is .RebootPending
The rest is for info purposes.
Function Get-PendingReboot {
<#
.SYNOPSIS
    Gets the pending reboot status on a local computer. Return 
    
.DESCRIPTION
    Queries the registry and WMI to determine if the system waiting for a reboot, from:
        CBServicing   = Component Based Servicing (Windows 2008)
        WindowsUpdate = Windows Update / Auto Update (Windows 2003 / 2008)
        CCMClientSDK  = SCCM 2012 Clients only (DetermineIfRebootPending method) otherwise $null value
        PendFileRename = PendingFileRenameOperations (Windows 2003 / 2008)
    
    Returns hash table similar to this:
    
    Computer       : MYCOMPUTERNAME
    LastBootUpTime : 01/12/2014 11:53:04 AM
    CBServicing    : False
    WindowsUpdate  : False
    CCMClientSDK   : False
    PendFileRename : False
    PendFileRenVal : 
    RebootPending  : False
    ErrorMsg       : 

    NOTES: 
    ErrorMsg only contains something if an error occurred

.EXAMPLE
    Get-PendingReboot
    
.EXAMPLE
    $PRB=Get-PendingReboot
    $PRB.RebootPending
    
.EXAMPLE
    #CAVEAT: Not fully tested but should work
    If ( ${Get-PendingReboot}.RebootPending ) { echo "need to reboot" } Else { echo "no reboots pending" }
        
.NOTES
    Based On: http://gallery.technet.microsoft.com/scriptcenter/Get-PendingReboot-Query-bdb79542
#>
    [CmdletBinding()]
    Begin {
        ## Get the name of this function and write header
        [string]${CmdletName} = $PSCmdlet.MyInvocation.MyCommand.Name
        Write-FunctionHeaderOrFooter -CmdletName ${CmdletName} -CmdletBoundParameters $PSBoundParameters -Header
        
        [String]$ComputerName="$envComputerName"
        $CBSRebootPend=$null
        $WUAURebootReq=$null
        $SCCM=$null
        $PendFileRename=$null
        $RegValuePFRO=$null
        $Pending=$null
        $LastBootUpTime=$null
        $PendRebootErrorMsg=$null
    }
    
    Process {
        Try {
            # Setting pending values to false to cut down on the number of else statements
            $PendFileRename,$Pending,$SCCM = $false,$false,$false
            
            # Setting CBSRebootPend to null since not all versions of Windows has this value
            $CBSRebootPend = $null
            
            Try {
                # Querying WMI for build version
                $WMI_OS = Get-WmiObject -Class Win32_OperatingSystem -ComputerName $ComputerName
                $LastBootUpTime=$WMI_OS.ConvertToDateTime($WMI_OS.LastBootUpTime)
            } catch {
                [datetime]$LastBootUpTime=0 # returns January-01-01 12:00:00 AM
                $PendRebootErrorMsg="WMI: $($_.Exception.Message)"
            }
            
            # If Vista/2008 & Above query the CBS Reg Key
            If ($WMI_OS.BuildNumber -ge 6001) {
                If (Test-Path "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Component Based Servicing\RebootPending") {
                $CBSRebootPend=$true } else { $CBSRebootPend=$false }
            }   
            
            # Query WUAU from the registry
            If (Test-Path "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\WindowsUpdate\Auto Update\RebootRequired") {
            $WUAURebootReq=$true } else { $WUAURebootReq=$false }
            
            # Query PendingFileRenameOperations from the registry
            $key="HKLM:\SYSTEM\CurrentControlSet\Control\Session Manager\"
            $Value="PendingFileRenameOperations"
            If (Test-Path "$key\$Value" -ErrorAction SilentlyContinue)  {
                $RegValuePFRO=Get-ItemProperty -Path $key | Select $Value -ExpandProperty $Value -ErrorAction SilentlyContinue
            } else { $RegValuePFRO=$null }

            # If PendingFileRenameOperations has a value set $RegValuePFRO variable to $true
            If ($RegValuePFRO) {
                $PendFileRename = $true
            } else {
    #           $RegValuePFRO="<empty>"
                $PendFileRename = $false                
            }

            # Determine SCCM 2012 Client Reboot Pending Status
            # To avoid nested 'if' statements and unneeded WMI calls to determine if the CCM_ClientUtilities class exist, setting EA = 0
            $CCMClientSDK = $null
            $CCMSplat = @{
                NameSpace='ROOT\ccm\ClientSDK'
                Class='CCM_ClientUtilities'
                Name='DetermineIfRebootPending'
                ComputerName=$ComputerName
                ErrorAction='SilentlyContinue'
            }
            $CCMClientSDK = Invoke-WmiMethod @CCMSplat
            If ($CCMClientSDK) {
                If ($CCMClientSDK.ReturnValue -ne 0) {
                    Write-Warning "Error: DetermineIfRebootPending returned error code $($CCMClientSDK.ReturnValue)"
                }

                If ($CCMClientSDK.IsHardRebootPending -or $CCMClientSDK.RebootPending) {
                    $SCCM = $true
                }
            }                        
                            
        } Catch {
            Write-Warning "$ComputerName`: $_"
            $PendRebootErrorMsg=$_
        }
        
        # If any of the variables are true, set $Pending variable to $true
        # If the variables are a mixture of false and Null, $Pending variable becomes $false
        If ($CBSRebootPend -or $WUAURebootReq -or $SCCM -or $PendFileRename) {
                $Pending = $true
        }
            
        # Creating Custom PSObject and Select-Object Splat
        $SelectSplat = @{
            Property=('Computer','LastBootUpTime','CBServicing','WindowsUpdate','CCMClientSDK','PendFileRename','PendFileRenVal','RebootPending','ErrorMsg')
        }
        New-Object -TypeName PSObject -Property @{
            Computer=$WMI_OS.CSName
            CBServicing=$CBSRebootPend
            WindowsUpdate=$WUAURebootReq
            CCMClientSDK=$SCCM
            PendFileRename=$PendFileRename
            PendFileRenVal=$RegValuePFRO
            RebootPending=$Pending
            LastBootUpTime=$LastBootUpTime
            ErrorMsg=$PendRebootErrorMsg
        } | Select-Object @SelectSplat
    }
    End {
        Write-FunctionHeaderOrFooter -CmdletName ${CmdletName} -Footer
    }           
} #Get-PendingReboot Function
Jan 15, 2015 at 3:26 PM
When will the code be added to the AppDeployToolkitMain.ps1 file and default part of the AppDeployToolkit ?
Jan 15, 2015 at 7:31 PM
Edited Jan 15, 2015 at 7:37 PM
It doesn't. That's why it's in the "Toolkit Extensions" section.
I'm just a user like you. Not a Developer of App Deploy Toolkit.

If you want it to be added, raise an "Issue" and ask the developers to add it.

Meanwhile, you can cut-n-paste it inside AppDeployToolkitExtensions.ps1

Denis
Jan 15, 2015 at 11:56 PM
Hi,

I believe that code is really interesting and will done. But once you run that code then what should we do? Popup a restart message with a SCCM Fast retry? Just return an error and make the package fail? How the strategy will act on OSD?
Jan 16, 2015 at 7:06 PM
That is office politics. I do not deal with that.

This is why I currently only LOG the info.
I only use the info when someone tells me my package failed so that I can say that the machine probably needed to be rebooted first. (i.e. https://www.google.ca/search?q=.net+4.5+error+5100 )

And then we have a discussion about what could be done to prevent it.

Like I said: office politics.
Jan 17, 2015 at 2:33 AM
It might be or not office politics, a code is a code and then it might still good to share our experience and the way some problem are handle by different organisation. It is evident the computer need to be restart but if you are sending a package to thousands computers and 100 -200 computers need to be reboot then you need to plan something on your package.
Jan 23, 2015 at 4:28 PM
Thanks for the code, but I tried copy paste it into the AppDeployToolkitExtensions.ps1 (version 3.5.0) but that does not work.
Module [C:\Windows\ccmcache\oc\AppDeployToolkit\AppDeployToolkitMain.ps1] faile
d to load:
At C:\Windows\ccmcache\oc\AppDeployToolkit\AppDeployToolkitExtensions.ps1:71 ch
ar:5
+     [CmdletBinding()]
+     ~~~~~~~~~~~~~~~~~
Unexpected attribute 'CmdletBinding'.

At C:\Windows\ccmcache\oc\AppDeployToolkit\AppDeployToolkitExtensions.ps1:72 ch
ar:5
+     Begin {
+     ~~~~~
Unexpected token 'Begin' in expression or statement.


At C:\Windows\ccmcache\oc\ComputerRestartScript.ps1:82 char:3
+         . $moduleAppDeployToolkitMain
+         ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Jan 28, 2015 at 11:32 AM
This code is working :-)
# Function to check whether a reboot is pending
Function Get-PendingReboot {
    Write-Log "Checking whether a reboot is pending..."

    # Setting Component Based Servicing (Windows 2008/Windows 7) RebootPend to null since not all versions of Windows has this value
        [String]$ComputerName="$envComputerName"
        $CBSRebootPend=$null
        $WUAURebootReq=$null
        $SCCM=$null
        $PendFileRename=$null
        $RegValuePFRO=$null
        $Pending=$null
        $LastBootUpTime=$null
        $PendRebootErrorMsg=$null


    # Making registry connection to the local/remote computer
    #$RegCon = [Microsoft.Win32.RegistryKey]::OpenRemoteBaseKey([Microsoft.Win32.RegistryHive]"LocalMachine",$envComputerName)

        Try {
            # Querying WMI for build version
            $WMI_OS = Get-WmiObject -Class Win32_OperatingSystem -ComputerName $ComputerName
            $LastBootUpTime=$WMI_OS.ConvertToDateTime($WMI_OS.LastBootUpTime)
        } catch {
            [datetime]$LastBootUpTime=0 # returns January-01-01 12:00:00 AM
            $PendRebootErrorMsg="WMI: $($_.Exception.Message)"
        }

    # Query Component Based Servicing from the registry
    #$RegSubKeysCBS = $RegCon.OpenSubKey("SOFTWARE\Microsoft\Windows\CurrentVersion\Component Based Servicing\").GetSubKeyNames()
    #$CBSRebootPend = $RegSubKeysCBS -contains "RebootPending"
        # If Vista/2008 & Above query the CBS Reg Key
        If ($WMI_OS.BuildNumber -ge 6001) {
            If (Test-Path "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Component Based Servicing\RebootPending") {
            $CBSRebootPend=$true } else { $CBSRebootPend=$false }
        }   

    # Query WUAU from the registry
    #$RegWUAU = $RegCon.OpenSubKey("SOFTWARE\Microsoft\Windows\CurrentVersion\WindowsUpdate\Auto Update\")
    #$RegWUAURebootReq = $RegWUAU.GetSubKeyNames()
    #$WUAURebootReq = $RegWUAURebootReq -contains "RebootRequired"
        # Query WUAU from the registry
        If (Test-Path "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\WindowsUpdate\Auto Update\RebootRequired") {
        $WUAURebootReq=$true } else { $WUAURebootReq=$false }
            
    # Query PendingFileRenameOperations from the registry
    #$RegSubKeySM = $RegCon.OpenSubKey("SYSTEM\CurrentControlSet\Control\Session Manager\")
    #$RegValuePFRO = $RegSubKeySM.GetValue("PendingFileRenameOperations",$null)

        # Query PendingFileRenameOperations from the registry
        $key="HKLM:\SYSTEM\CurrentControlSet\Control\Session Manager\"
        $Value="PendingFileRenameOperations"
        If (Test-Path "$key\$Value" -ErrorAction SilentlyContinue)  {
            $RegValuePFRO=Get-ItemProperty -Path $key | Select $Value -ExpandProperty $Value -ErrorAction SilentlyContinue
        } else { $RegValuePFRO=$null }

    # Closing registry connection
    #$RegCon.Close()

        # If PendingFileRenameOperations has a value set $RegValuePFRO variable to $true
        If ($RegValuePFRO) {
            $PendFileRename = $true
        } else {
            $PendFileRename = $false                
        }

        # Determine SCCM 2012 Client Reboot Pending Status
        # To avoid nested 'if' statements and unneeded WMI calls to determine if the CCM_ClientUtilities class exist, setting EA = 0
        $CCMClientSDK = $null
        $CCMSplat = @{
            NameSpace='ROOT\ccm\ClientSDK'
            Class='CCM_ClientUtilities'
            Name='DetermineIfRebootPending'
            ComputerName=$ComputerName
            ErrorAction='SilentlyContinue'
        }
        $CCMClientSDK = Invoke-WmiMethod @CCMSplat
        If ($CCMClientSDK) {
            If ($CCMClientSDK.ReturnValue -ne 0) {
                Write-Warning "Error: DetermineIfRebootPending returned error code $($CCMClientSDK.ReturnValue)"
            }
             If ($CCMClientSDK.IsHardRebootPending -or $CCMClientSDK.RebootPending) {
                $SCCM = $true
            }
        }                        
                            
    # If any of the variables are true, set $Pending variable to $true
    If ($CBSRebootPend -or $WUAURebootReq -or $SCCM -or $PendFileRename) {
        $Pending = $true
        Write-Log "This system has a pending reboot"
        Return $true
    }

    $Pending = $false
    Write-Log "This system has no pending reboot"
    Return $false
}
Feb 4, 2015 at 7:01 AM
I found out that the Powershell "Test-Path" command is not always working correctly. For that I changed my code to:
<#
.SYNOPSIS
    This script is a template that allows you to extend the toolkit with your own custom functions.
.DESCRIPTION
    The script is automatically dot-sourced by the AppDeployToolkitMain.ps1 script.
.NOTES
.LINK 
    http://psappdeploytoolkit.codeplex.com
#>
[CmdletBinding()]
Param (
)

##*===============================================
##* VARIABLE DECLARATION
##*===============================================

# Variables: Script
[string]$appDeployToolkitExtName = 'PSAppDeployToolkitExt'
[string]$appDeployExtScriptFriendlyName = 'App Deploy Toolkit Extensions'
[version]$appDeployExtScriptVersion = [version]'1.5.0'
[string]$appDeployExtScriptDate = '11/06/2014'
[hashtable]$appDeployExtScriptParameters = $PSBoundParameters

##*===============================================
##* FUNCTION LISTINGS
##*===============================================

# Function to check registry keys since Test-Path is not always working correctly
Function Test-RegistryKeyValue
{
    <#
    .SYNOPSIS
    Tests if a registry value exists.

    .DESCRIPTION
    The usual ways for checking if a registry value exists don't handle when a value simply has an empty or null value.  This function actually checks if a key has a value with a given name.

    .EXAMPLE
    Test-RegistryKeyValue -Path 'hklm:\Software\Carbon\Test' -Name 'Title'

    Returns `True` if `hklm:\Software\Carbon\Test` contains a value named 'Title'.  `False` otherwise.
    #>
    [CmdletBinding()]
    param(
        [Parameter(Mandatory=$true)]
        [string]
        # The path to the registry key where the value should be set.  Will be created if it doesn't exist.
        $Path,
        [Parameter(Mandatory=$true)]
        [string]
        # The name of the value being set.
        $Name
    )
    if( -not (Test-Path -Path $Path -PathType Container) )
    {
        return $false
    }
    $properties = Get-ItemProperty -Path $Path 
    if( -not $properties )
    {
        return $false
    }
    $member = Get-Member -InputObject $properties -Name $Name
    if( $member )
    {
        return $true
    }
    else
    {
        return $false
    }
}

# Function to check whether a reboot is pending
Function Get-PendingReboot {
    Write-Log "Checking whether a reboot is pending..."

    # Setting Component Based Servicing (Windows 2008/Windows 7) RebootPend to null since not all versions of Windows has this value
        [String]$ComputerName="$envComputerName"
        $CBSRebootPend=$null
        $WUAURebootReq=$null
        $SCCM=$null
        $PendFileRename=$null
        $RegValuePFRO=$null
        $Pending=$null
        $LastBootUpTime=$null
        $PendRebootErrorMsg=$null


    # Making registry connection to the local/remote computer
    #$RegCon = [Microsoft.Win32.RegistryKey]::OpenRemoteBaseKey([Microsoft.Win32.RegistryHive]"LocalMachine",$envComputerName)

        Try {
            # Querying WMI for build version
            $WMI_OS = Get-WmiObject -Class Win32_OperatingSystem -ComputerName $ComputerName
            $LastBootUpTime=$WMI_OS.ConvertToDateTime($WMI_OS.LastBootUpTime)
        } catch {
            [datetime]$LastBootUpTime=0 # returns January-01-01 12:00:00 AM
            $PendRebootErrorMsg="WMI: $($_.Exception.Message)"
        }

    # Query Component Based Servicing from the registry
    #$RegSubKeysCBS = $RegCon.OpenSubKey("SOFTWARE\Microsoft\Windows\CurrentVersion\Component Based Servicing\").GetSubKeyNames()
    #$CBSRebootPend = $RegSubKeysCBS -contains "RebootPending"
        # If Vista/2008 & Above query the CBS Reg Key
        If ($WMI_OS.BuildNumber -ge 6001) {
            #If (Test-Path "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Component Based Servicing\RebootPending") {
        If (Test-RegistryKeyValue -Path 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Component Based Servicing' -Name 'RebootPending') {
            $CBSRebootPend=$true } else { $CBSRebootPend=$false }
        }

    # Query WUAU from the registry
    #$RegWUAU = $RegCon.OpenSubKey("SOFTWARE\Microsoft\Windows\CurrentVersion\WindowsUpdate\Auto Update\")
    #$RegWUAURebootReq = $RegWUAU.GetSubKeyNames()
    #$WUAURebootReq = $RegWUAURebootReq -contains "RebootRequired"
        # Query WUAU from the registry
        #If (Test-Path "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\WindowsUpdate\Auto Update\RebootRequired") {
    If (Test-RegistryKeyValue -Path 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\WindowsUpdate\Auto Update' -Name 'RebootRequired') {
        $WUAURebootReq=$true } else { $WUAURebootReq=$false }
            
    # Query PendingFileRenameOperations from the registry
    #$RegSubKeySM = $RegCon.OpenSubKey("SYSTEM\CurrentControlSet\Control\Session Manager\")
    #$RegValuePFRO = $RegSubKeySM.GetValue("PendingFileRenameOperations",$null)

        # Query PendingFileRenameOperations from the registry
        $key="HKLM:\SYSTEM\CurrentControlSet\Control\Session Manager\"
        $Value="PendingFileRenameOperations"
        #If (Test-Path "$key\$Value" -ErrorAction SilentlyContinue)  {
    If (Test-RegistryKeyValue -Path "$key" -Name "$Value") {
            $RegValuePFRO=Get-ItemProperty -Path $key | Select $Value -ExpandProperty $Value -ErrorAction SilentlyContinue
        } else { $RegValuePFRO=$null }

    # Closing registry connection
    #$RegCon.Close()

        # If PendingFileRenameOperations has a value set $RegValuePFRO variable to $true
        If ($RegValuePFRO) {
            $PendFileRename = $true
        } else {
            $PendFileRename = $false                
        }

        # Determine SCCM 2012 Client Reboot Pending Status
        # To avoid nested 'if' statements and unneeded WMI calls to determine if the CCM_ClientUtilities class exist, setting EA = 0
        $CCMClientSDK = $null
        $CCMSplat = @{
            NameSpace='ROOT\ccm\ClientSDK'
            Class='CCM_ClientUtilities'
            Name='DetermineIfRebootPending'
            ComputerName=$ComputerName
            ErrorAction='SilentlyContinue'
        }
        $CCMClientSDK = Invoke-WmiMethod @CCMSplat
        If ($CCMClientSDK) {
            If ($CCMClientSDK.ReturnValue -ne 0) {
                Write-Warning "Error: DetermineIfRebootPending returned error code $($CCMClientSDK.ReturnValue)"
            }
             If ($CCMClientSDK.IsHardRebootPending -or $CCMClientSDK.RebootPending) {
                $SCCM = $true
            }
        }                        
                            
    # If any of the variables are true, set $Pending variable to $true
    If ($CBSRebootPend -or $WUAURebootReq -or $SCCM -or $PendFileRename) {
        $Pending = $true
        Write-Log "This system has a pending reboot"
        Return $true
    }

    $Pending = $false
    Write-Log "This system has no pending reboot"
    Return $false
}

##*===============================================
##* END FUNCTION LISTINGS
##*===============================================

##*===============================================
##* SCRIPT BODY
##*===============================================

If ($scriptParentPath) {
    Write-Log -Message "Script [$($MyInvocation.MyCommand.Definition)] dot-source invoked by [$(((Get-Variable -Name MyInvocation).Value).ScriptName)]" -Source $appDeployToolkitExtName
}
Else {
    Write-Log -Message "Script [$($MyInvocation.MyCommand.Definition)] invoked directly" -Source $appDeployToolkitExtName
}

##*===============================================
##* END SCRIPT BODY
##*===============================================
Feb 4, 2015 at 11:57 PM
Hi,

Interesting but as I believe it would be better to include it in PSADT. If I remember correclt there is already a function to check registry key so why not using it?

Thanks,
Feb 5, 2015 at 7:37 AM
Hi Siocnarf,

Which function ? I only know the default Powershell Test-Path and that function does not always work correctly on registry "values".
Feb 5, 2015 at 10:44 AM
Get-registrykey
Feb 5, 2015 at 11:28 AM
Edited Feb 5, 2015 at 11:31 AM
Hi Siocnarf,

Yes i have seen that function Get-RegistryKey.
But also, as described in the function header, you should use Test-Path to test if a key/value exist.
And test-path is not working always correctly for "values".

So a Test-RegistryKey function is required in the appdeploytoolkit which always work.
I will add it to the feature requests...


Check: TEXT
Feb 5, 2015 at 1:24 PM
I tried your script and don't understand:
If ($scriptParentPath) {
    Write-Log -Message "Script [$($MyInvocation.MyCommand.Definition)] dot-source invoked by [$(((Get-Variable -Name MyInvocation).Value).ScriptName)]" -Source $appDeployToolkitExtName
}
Else {
    Write-Log -Message "Script [$($MyInvocation.MyCommand.Definition)] invoked directly" -Source $appDeployToolkitExtName
}
About test-path, did you open a case on PSADT as it might impact many scripts functionnality?
What is the exact behavior you are saying?
Feb 6, 2015 at 3:50 AM
Hi,

I tried several times to load properly your script but there is always an error.

I am copying it in a script call main.ps1 then I have another script dot-sourcing PSAppdeploytoolkitmain.ps1 and main.ps1. Everytime i get an error about the cmdletbinding or this one:
La propriété « __Value__ » est introuvable dans cet objet. Vérifiez qu’elle existe. 
Au caractère C:\Temp\Vcredist2005_Frv1\_include\main.ps1:398 : 5
+     Write-Log -Message "Script [$($MyInvocation.MyCommand.Definition)] dot-sourc ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
In English it would say Value property not found at line 398
 Write-Log -Message "Script [$($MyInvocation.MyCommand.Definition)] dot-source invoked by [$(((Get-Variable -Name MyInvocation).Value).ScriptName)]" -Source $appDeployToolkitExtName
Feb 6, 2015 at 6:58 AM
Siocnarf wrote:
I tried your script and don't understand:
If ($scriptParentPath) {
    Write-Log -Message "Script [$($MyInvocation.MyCommand.Definition)] dot-source invoked by [$(((Get-Variable -Name MyInvocation).Value).ScriptName)]" -Source $appDeployToolkitExtName
}
Else {
    Write-Log -Message "Script [$($MyInvocation.MyCommand.Definition)] invoked directly" -Source $appDeployToolkitExtName
}
About test-path, did you open a case on PSADT as it might impact many scripts functionnality?
What is the exact behavior you are saying?
Hi Siocnarf,
That code is part of the AppDeployToolkitExtensions.ps1 default provided by the AppDeployToolkit. That is not my code. It is AppDeployToolkit code.
Feb 10, 2015 at 2:18 AM
Hi,

You did remove these informations. I believe it was good to know where it was failing for diagnosis purposes.

New-Object -TypeName PSObject -Property @{
    Computer=$WMI_OS.CSName
    CBServicing=$CBSRebootPend
    WindowsUpdate=$WUAURebootReq
    CCMClientSDK=$SCCM
    PendFileRename=$PendFileRename
    PendFileRenVal=$RegValuePFRO
    RebootPending=$Pending
    LastBootUpTime=$LastBootUpTime
    ErrorMsg=$PendRebootErrorMsg
} | Select-Object @SelectSplat
Thanks,
Feb 10, 2015 at 7:23 AM
Ooops. I dis not know why that code was there.
Do i removed it because it seems to me useless to me for the script ?

But it isn't ?
Feb 10, 2015 at 11:02 AM
Will you correct your script? Actually, it is returning $true or $false.