Use PowerShell to test if a Windows server is pending a reboot.

To prevent service interruptions, you have to schedule Windows server reboots. With the help of PowerShell, you can check whether a particular Windows server requires a reboot or not.

Unfortunately, we can't always keep our servers up 24/7. In Windowsland especially, a reboot now and then is required. There are many different reasons a server may need a reboot, like software that needs to modify something currently running, a locked file that refuses to let go without a boot, or perhaps a service that can only apply a change at boot time.

The solution to a needed reboot is simple: reboot it! But it's not always that simple. Servers are serving users, and users don't like it when their services go down at any time. Also, if you manage a lot of servers, you may want to schedule a maintenance window to reboot them all at once rather than as needed. In such a case, you need to know which ones need rebooting and which ones don't. How to determine that isn't too clear on a Windows server.

There is no one area to look at to tell whether a Windows server needs a reboot. The flags are spread out amongst a few different registry keys. Luckily, we can use a PowerShell script to query these registry values and return a simple True or False to indicate if one or more servers need a three-finger salute.

Before we get to the PowerShell, you need to understand where to look. There are three (or more I'm not aware of) registry values you should check to see whether a reboot is needed or not.

  • The RebootPending value at
    HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Component Based Servicing
  • The RebootRequired value at
    HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\WindowsUpdate\Auto Update
  • The PendingFileRenameOperations value at
    HKLM:\SYSTEM\CurrentControlSet\Control\Session Manager

Knowing these registry values, we then create the PowerShell code to check for them on a remote server. We'll do this over PowerShell Remoting, so I'm assuming it is available on your servers.

The server is pending a reboot if the RebootPending and RebootRequired values exist. Let's build some code to check for these registry values' existence. I'm getting a little fancy here by creating an array of hash tables. I'm doing this because it makes it easier to add more checks if one day you find out you need to check other registry values. Using an array like this will allow me to loop over each test quickly.

Also, notice below I'm ignoring errors because if it throws an error, I'm going to assume the value does not exist.

$pendingRebootTests = @(
    @{
        Name = 'RebootPending'
        Test = { Get-ItemProperty -Path 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Component Based Servicing'  Name 'RebootPending' -ErrorAction Ignore }
        TestType = 'ValueExists'
    }
    @{
        Name = 'RebootRequired'
        Test = { Get-ItemProperty -Path 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\WindowsUpdate\Auto Update'  Name 'RebootRequired' -ErrorAction Ignore }
        TestType = 'ValueExists'
    }
    @{
        Name = 'PendingFileRenameOperations'
        Test = { Get-ItemProperty -Path 'HKLM:\SYSTEM\CurrentControlSet\Control\Session Manager' -Name 'PendingFileRenameOperations' -ErrorAction Ignore }
        TestType = 'NonNullValue'
    }
)

Now that we have the code built to run the tests, let's create a PowerShell Remoting session and run these scriptblocks on a server.

## Create a PowerShell Remoting session
$session = New-PSSession -Computer SRV1
foreach ($test in $pendingRebootTests) {
    Invoke-Command -Session $session -ScriptBlock $test.Test
}

This will run the code on all the servers but won't return a simple True or False as we need. To do this, we need to add some if/then logic to it. Since only two of the tests need to return True or False if the registry key exists or not, we'll use the TestType key in each hash table to make that distinction.

Subscribe to 4sysops newsletter!

$session = New-PSSession -Computer SRV1
foreach ($test in $pendingRebootTests) {
    $result = Invoke-Command -Session $session -ScriptBlock $test.Test
    if ($test.TestType -eq 'ValueExists' -and $result) {
        $true
    } elseif ($test.TestType -eq 'NonNullValue' -and $result -and $result.($test.Name)) {
        $true
    } else {
        $false
    }
}
$session | Remove-PSSession
Pending reboot test

Pending reboot test

At this point, we can get an output from this server with the results of each of the checks we've done. This function is also built to expand upon by adding additional servers if need be.

avataravataravatar
18 Comments
  1. Itamar Tziger 4 years ago

    Hi,

    From where do you have $test? 

     

    Br, 

    Itamar

    • Leos Marek (Rank 4) 4 years ago

      That is how foreach and other things in Powershell work. You need to check a bit about Powershell basics.

      foreach ($test in $pendingRebootTests) {
      Write-host $test
      }

      This code is taking each item in $pendingRebootTests, puts it to variable $test and then process it. You could replace $test with $abc or whatever you want.

      avataravatar
  2. Rufus 4 years ago

    Why in the world would anyone, especially well into the internet age, still use Windows?

    • Because Edge is not yet available for Linux? 😉

    • SamIAm 3 years ago

      Why would anyone continue to use frameworks that have to be built from scratch? 
      Consider that Linux dev's invented Docker/Kubernetes because they could never count on any linux server to have a baseline framework.

  3. Itamar Tziger 4 years ago

    I miss the forech loop.

     

    Tnx.

  4. Eric Simbozel 4 years ago

    doesn't work on windows server 2016, can't find key name in registry

    • Hi Eric, The keys mentioned in the above articles are commonly used in many Windows Server OS.

      And these are present at least since 2012 build till now. Here is one simulation. 

      Server that doesn't need to be rebooted for pending files:

      C:\>reg query "\\server1\hklm\System\CurrentControlSet\Control\Session Manager" /v PendingFileRenameOperations

      ERROR: The system was unable to find the specified registry key or value.

      Server that does need to be rebooted for pending files:

      C:\>reg query "\\server2\hklm\System\CurrentControlSet\Control\Session Manager" /v PendingFileRenameOperations

      HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Session Manager
          PendingFileRenameOperations    REG_MULTI_SZ    \??\C:\WINDOWS\system32\SET2B5.tmp\0!\??\C:\WINDOWS\system32\schannel.dll\0\??\C:\WINDOWS\system32\_000025_.tmp.dll\0\??

       

      • Is the solution complete? No. As the author mentioned there are some other keys as well which would denote 'Server Reboot Required' Event. Once we include all the keys then the reliability of the output would further increase.  In this article, the Author has covered the most commonly occurring events that necessitated 'Server Reboot'

  5. David Zampino 4 years ago

    If you use SCCM, you have to check in the WMI Database for pending reboots. In the PowerShell Gallery there is a module that covers these edge cases as well PendingReboot.

    avatar
  6. Paul G 3 years ago

    Your code doesn't produce the table output in your screensho. Can you please advise how you managed that output format?

    • Leos Marek (Rank 4) 3 years ago
      $result
      $session | Remove-PSSession

      Without any further testing I would say to add this at the end

       

    • ajnabi 3 years ago

      Same case with me, please guide or share complete script.

      thanks. 

  7. See Sharper 3 years ago

    Great script but there are two typos in $pendingRebootTests you forgot the dash before Name in the first two Get-Item… registry calls. Thanks for sharing!

  8. ajnabi 3 years ago

    Hi 

    Please share complete script as i compiled it but not showing output in tabular format.

  9. EricBonin 2 years ago

    hello,

    there is a typo in the first two registry check, name should be -name.

    Also it make sense for me to get the added boolean result of the 3 reg key, if one is true then the server has a pending reboot, if they are all false then not.

    example below:

    $rebootstate=$null
    foreach ($test in $pendingRebootTests) {
        $result = Invoke-Command -Session $session -ScriptBlock $test.Test
        if ($test.TestType -eq 'ValueExists' -and $result) {
            $state=$true
        } elseif ($test.TestType -eq 'NonNullValue' -and $result -and $result.($test.Name)) {
            $state=$true
        } else {
            $state+=$false
        }
    $rebootstate= $rebootstate -or $state
    }
    $rebootstate
    $session | Remove-PSSession

  10. EricBonin 2 years ago

    hello,

    there is a typo in the first two registry check, name should be -name.

    Also it make sense for me to get the added boolean result of the 3 reg key, if one is true then the server has a pending reboot, if they are all false then not.

    example below:

    $session = New-PSSession -Computer exchange01
    $rebootstate=$null
    foreach ($test in $pendingRebootTests) {
        $result = Invoke-Command -Session $session -ScriptBlock $test.Test
        if ($test.TestType -eq 'ValueExists' -and $result) {
            $state=$true
        } elseif ($test.TestType -eq 'NonNullValue' -and $result -and $result.($test.Name)) {
            $state=$true
        } else {
            $state=$false
        }
    $rebootstate= $rebootstate -or $state
    }
    $rebootstate
    $session | Remove-PSSession

Leave a reply

Your email address will not be published.

*

© 4sysops 2006 - 2023

CONTACT US

Please ask IT administration questions in the forums. Any other messages are welcome.

Sending

Log in with your credentials

or    

Forgot your details?

Create Account