This article contains functions and features that are not documented by the original manufacturer. By following advice in this article, you're doing so at your own risk. The methods presented in this article may rely on internal implementation and may not work in the future.
Intro
In this blog post I want to share the results of our research into the undocumented world of updates in Windows 10, and namely, how do you control whether or not those updates are installed during a reboot (or shutdown), and how to find out if a restart is necessary to finish installation of updates.
This blog post is intended for the Windows developers. In case you are just an end-user that wants to take advantage of this research, please download our software that does that. It is called ShutdownWithUpdates.
Table Of Contents
Here's the table of contents for a quick access:
- Reboot To Install Updates
- Reboot Without Installing Updates
- Reboot Or Shutdown
- Check If Reboot Is Required To Install Updates
- Conclusion
Reboot To Install Updates
This may be necessary since Microsoft decided to have users click this button to finish installation of updates:
But what if you have 100, or 1000 computers that you need to click that button for? How are you supposed to do that?
In that case, you can automate it in your script, or in your software, to simply set the following System Registry key, before initiating a restart:
[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\WindowsUpdate\Orchestrator\InstallAtShutdown]
(Default) = REG_DWORD: 1
Note that this key is a redirected one in a 32-bit process that is running under a 64-bit OS.
You can also do it using the code like this:
//Enable installation of updates during the next reboot
DWORD dwV = 1;
if(!WriteValueToSystemRegistry(HKEY_LOCAL_MACHINE, TRUE,
L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\WindowsUpdate\\Orchestrator\\InstallAtShutdown",
NULL, REG_DWORD, &dwV, sizeof(dwV)))
{
//Failed - log OS error code from GetLastError()
assert(false);
}
Note that we're using our WriteValueToSystemRegistry
helper function to be able to access a 64-bit registry from a 32-bit process:
BOOL WriteValueToSystemRegistry(HKEY hIniKey, BOOL bWOW64, LPCTSTR lpSubKey, LPCTSTR lpKeyValue, DWORD dwValueType, const void* pData, int ncbDataSz)
{
HKEY hKey;
DWORD dwR;
REGSAM dwSam;
BOOL bRes = FALSE;
#ifdef _M_X64
//64-bit build
dwSam = KEY_SET_VALUE;
#else
//32-bit build
dwSam = KEY_SET_VALUE | (bWOW64 ? KEY_WOW64_64KEY : 0);
#endif
dwR = RegCreateKeyEx(hIniKey, lpSubKey, NULL, NULL, 0, dwSam, NULL, &hKey, NULL);
if(dwR == ERROR_SUCCESS)
{
if((dwR = RegSetValueEx(hKey, lpKeyValue, NULL, dwValueType, (const BYTE *)pData, ncbDataSz)) == ERROR_SUCCESS)
{
bRes = TRUE;
}
RegCloseKey(hKey);
}
SetLastError(dwR);
return bRes;
}
Note that Microsoft actually set up a DACL on the InstallAtShutdown
registry key to enable all authenticated users to set its value.
This means that your code doesn't have to run with administrative privileges to do what I showed above.
Note that the InstallAtShutdown
registry setting has no effect by itself if Windows updates are not downloaded, or otherwise are ready for an installation during a reboot.
Reboot Without Installing Updates
Note that I'm talking about preventing installation of updates during a reboot or shutdown only. This may be necessary if you don't want to lock up your PC for half an hour (to install an update) and just need to reboot it quickly. Also having such option in your software may be a good thing to give your users control over their computers.
Here's how you can do it: you basically need to set the following System Registry values before you initiate a reboot:
[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\WindowsUpdate\Orchestrator\InstallAtShutdown]
(Default) = REG_DWORD: 0
[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\WindowsUpdate\CommitStatus]
"NoCommit" = REG_DWORD: 1
Note that these keys are redirected in a 32-bit process that is running under a 64-bit OS.
Note that the CommitStatus
registry key may not be reset in some circumstances during a reboot. Thus it is advisable to remove it as soon as your service starts running again.
Failure to do so may prevent further installation of Windows updates!
You can achieve it using this code:
//To prevent installation of updates during the next reboot
DWORD dwV = 1;
if(WriteValueToSystemRegistry(HKEY_LOCAL_MACHINE, TRUE,
L"SOFTWARE\\Microsoft\\WindowsUpdate\\CommitStatus", L"NoCommit", REG_DWORD, &dwV, sizeof(dwV)))
{
dwV = 0;
if(!WriteValueToSystemRegistry(HKEY_LOCAL_MACHINE, TRUE,
L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\WindowsUpdate\\Orchestrator\\InstallAtShutdown", NULL,
REG_DWORD, &dwV, sizeof(dwV)))
{
//Failed - log OS error code from GetLastError()
assert(false);
}
}
else
{
//Failed - log OS error code from GetLastError()
assert(false);
}
We used our WriteValueToSystemRegistry
helper function again.
Note that the code above must be running as administrator to be able to write into the CommitStatus
key.
Interestingly enough, the InstallAtShutdown
key seems to be open for writing by users without administrative privileges.
Reboot Or Shutdown
Then the reboot (or shutdown) is performed using the exact same function as you would do it otherwise:
int nOSError = InitiateShutdown(NULL, NULL, 0, dwPowerOpFlags,
SHTDN_REASON_MAJOR_OTHER | SHTDN_REASON_MINOR_OTHER | SHTDN_REASON_FLAG_PLANNED);
if(nOSError != ERROR_SUCCESS)
{
//Failed - log OS error code in nOSError
assert(false);
}
Where dwPowerOpFlags
can be set to SHUTDOWN_RESTART
for a reboot, or to SHUTDOWN_POWEROFF
for a shutdown. Microsoft also likes to OR it with the
SHUTDOWN_RESTARTAPPS
flag to enable supporting apps
to restore their data after a restart.
Additionally, the InitiateShutdown
API requires
the SE_SHUTDOWN_PRIVILEGE
privilege to be enabled. You can do it with a
helper function like this before you invoke InitiateShutdown
:
Note that the InstallAtShutdown
registry key mentioned above will be reset during a reboot.
Check If Reboot Is Required To Install Updates
And finally, how can you tell if a reboot is required to finish installation of updates?
You can use the presence of the following registry key to check that:
[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\WindowsUpdate\Orchestrator\RebootRequired]
Note that this key is a redirected one in a 32-bit process that is running under a 64-bit OS.
You can read that key using the code like this:
HKEY hKey;
DWORD dwR = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\WindowsUpdate\\Orchestrator\\RebootRequired", 0,
#ifdef _M_X64
//64-bit build
KEY_READ,
#else
//32-bit build
KEY_READ | KEY_WOW64_64KEY,
#endif
&hKey);
if (dwR == ERROR_SUCCESS)
{
//Reboot is required to install updates
RegCloseKey(hKey);
}
else if(dwR == ERROR_FILE_NOT_FOUND)
{
//Reboot is not required to install updates
}
else
{
//Failed - log OS error code in dwR
assert(false);
}
Note that the code above does not have to run elevated to read that key.
Conclusion
In conclusion, let me say that this is a highly undocumented stuff. If you rely on it in your software, be prepared to have it changed by Microsoft in one of their future updates. I went through this several times already in the ShutdownWithUpdates tool.