- Create a certificate-signed RDP shortcut via Group Policy - Fri, Aug 9 2019
- Monitor web server uptime with a PowerShell script - Tue, Aug 6 2019
- How to build a PowerShell inventory script for Windows Servers - Fri, Aug 2 2019
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
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.
Hi,
From where do you have $test?
Br,
Itamar
That is how foreach and other things in Powershell work. You need to check a bit about Powershell basics.
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.
Why in the world would anyone, especially well into the internet age, still use Windows?
Because Edge is not yet available for Linux? 😉
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.
I miss the forech loop.
Tnx.
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'
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.
https://gallery.technet.microsoft.com/scriptcenter/Get-PendingReboot-Query-bdb79542
Your code doesn't produce the table output in your screensho. Can you please advise how you managed that output format?
Without any further testing I would say to add this at the end
Same case with me, please guide or share complete script.
thanks.
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!
Hi
Please share complete script as i compiled it but not showing output in tabular format.
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:
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: