Controlling access to Windows Update is a vital aspect of endpoint management. For IT professionals and Managed Service Providers (MSPs), the ability to disable or enable the “Check for Updates” button can be the difference between a stable operating environment and a wave of unexpected patching across dozens—or thousands—of machines. This PowerShell script offers a programmatic way to lock down that button or restore user access, helping IT teams maintain consistent update policies.
Background
Microsoft Windows allows users to manually trigger update checks through the “Check for Updates” button in the Windows Update settings. However, in many enterprise environments, uncoordinated updates can interfere with patch management schedules, cause compatibility issues, or lead to downtime. Group Policy offers a way to control update behavior, but not every environment is domain-joined or centrally managed.
That’s where this PowerShell script comes in. It empowers administrators to toggle the visibility and functionality of the “Check for Updates” button by modifying a specific registry setting. This approach is especially useful for environments where Group Policy is not in use or where more granular, on-demand control is required.
The Script
#Requires -Version 5.1 <# .SYNOPSIS Disable or enable the 'Check for Updates' button in Windows Update. .DESCRIPTION Disable or enable the 'Check for Updates' button in Windows Update. By using this script, you indicate your acceptance of the following legal terms as well as our Terms of Use at https://www.ninjaone.com/terms-of-use. Ownership Rights: NinjaOne owns and will continue to own all right, title, and interest in and to the script (including the copyright). NinjaOne is giving you a limited license to use the script in accordance with these legal terms. Use Limitation: You may only use the script for your legitimate personal or internal business purposes, and you may not share the script with another party. Republication Prohibition: Under no circumstances are you permitted to re-publish the script in any script library or website belonging to or under the control of any other software provider. Warranty Disclaimer: The script is provided “as is” and “as available”, without warranty of any kind. NinjaOne makes no promise or guarantee that the script will be free from defects or that it will meet your specific needs or expectations. Assumption of Risk: Your use of the script is at your own risk. You acknowledge that there are certain inherent risks in using the script, and you understand and assume each of those risks. Waiver and Release: You will not hold NinjaOne responsible for any adverse or unintended consequences resulting from your use of the script, and you waive any legal or equitable rights or remedies you may have against NinjaOne relating to your use of the script. EULA: If you are a NinjaOne customer, your use of the script is subject to the End User License Agreement applicable to you (EULA). .EXAMPLE -Action "Disable" Attempting to disable the 'Check for Updates' button. Set Registry::HKEY_LOCAL_MACHINE\Software\Policies\Microsoft\Windows\WindowsUpdate\SetDisableUXWUAccess to 1 Successfully disabled the 'Check for Updates' button. PARAMETER: -Action "Enable" Specify whether the 'Check for Updates' button should be accessible for all users of this machine. .NOTES Minimum OS Architecture Supported: Windows 10, Windows Server 2016 Release Notes: Initial Release #> [CmdletBinding()] param ( [Parameter()] [String]$Action ) begin { # If script form variables are used, replace the command line parameters with their value. if ($env:action -and $env:action -notlike "null") { $Action = $env:action } # Check if the $Action variable is set if ($Action) { $Action = $Action.Trim() } # If $Action is null or empty after trimming any leading and trailing whitespace, display an error message and exit if (!$Action) { Write-Host -Object "[Error] A valid action must be provided." exit 1 } # Define a list of valid actions: "Enable" and "Disable" $ValidActions = "Enable", "Disable" # Check if the value of $Action is not in the list of valid actions if ($ValidActions -notcontains $Action) { Write-Host -Object "[Error] Invalid action '$Action' specified. Please specify either 'Enable' or 'Disable'." exit 1 } function Set-RegKey { param ( $Path, $Name, $Value, [ValidateSet("DWord", "QWord", "String", "ExpandedString", "Binary", "MultiString", "Unknown")] $PropertyType = "DWord" ) # Check if the specified registry path exists if (!(Test-Path -Path $Path)) { try { # If the path does not exist, create it New-Item -Path $Path -Force -ErrorAction Stop | Out-Null } catch { # If there is an error creating the path, output an error message and exit Write-Host "[Error] Unable to create the registry path $Path for $Name. Please see the error below!" Write-Host "[Error] $($_.Exception.Message)" exit 1 } } # Check if the registry key already exists at the specified path if (Get-ItemProperty -Path $Path -Name $Name -ErrorAction SilentlyContinue) { # Retrieve the current value of the registry key $CurrentValue = (Get-ItemProperty -Path $Path -Name $Name -ErrorAction SilentlyContinue).$Name if ($CurrentValue -eq $Value) { Write-Host "$Path\$Name is already the value '$Value'." } else { try { # Update the registry key with the new value Set-ItemProperty -Path $Path -Name $Name -Value $Value -Force -Confirm:$false -ErrorAction Stop | Out-Null } catch { # If there is an error setting the key, output an error message and exit Write-Host "[Error] Unable to set registry key for $Name at $Path. Please see the error below!" Write-Host "[Error] $($_.Exception.Message)" exit 1 } # Output the change made to the registry key Write-Host "$Path\$Name changed from $CurrentValue to $((Get-ItemProperty -Path $Path -Name $Name -ErrorAction SilentlyContinue).$Name)" } } else { try { # If the registry key does not exist, create it with the specified value and property type New-ItemProperty -Path $Path -Name $Name -Value $Value -PropertyType $PropertyType -Force -Confirm:$false -ErrorAction Stop | Out-Null } catch { # If there is an error creating the key, output an error message and exit Write-Host "[Error] Unable to set registry key for $Name at $Path. Please see the error below!" Write-Host "[Error] $($_.Exception.Message)" exit 1 } # Output the creation of the new registry key Write-Host "Set $Path\$Name to $((Get-ItemProperty -Path $Path -Name $Name -ErrorAction SilentlyContinue).$Name)" } } function Test-IsDomainController { # Determine the method to retrieve the operating system information based on PowerShell version try { $OS = if ($PSVersionTable.PSVersion.Major -lt 3) { Get-WmiObject -Class Win32_OperatingSystem -ErrorAction Stop } else { Get-CimInstance -ClassName Win32_OperatingSystem -ErrorAction Stop } } catch { Write-Host -Object "[Error] Unable to validate whether or not this device is a domain controller." Write-Host -Object "[Error] $($_.Exception.Message)" exit 1 } # Check if the ProductType is "2", which indicates that the system is a domain controller if ($OS.ProductType -eq "2") { return $true } } function Test-IsDomainJoined { # Check the PowerShell version to determine the appropriate cmdlet to use try { if ($PSVersionTable.PSVersion.Major -lt 3) { return $(Get-WmiObject -Class Win32_ComputerSystem).PartOfDomain } else { return $(Get-CimInstance -Class Win32_ComputerSystem).PartOfDomain } } catch { Write-Host -Object "[Error] Unable to validate whether or not this device is a part of a domain." Write-Host -Object "[Error] $($_.Exception.Message)" exit 1 } } function Test-IsElevated { $id = [System.Security.Principal.WindowsIdentity]::GetCurrent() $p = New-Object System.Security.Principal.WindowsPrincipal($id) $p.IsInRole([System.Security.Principal.WindowsBuiltInRole]::Administrator) } if (!$ExitCode) { $ExitCode = 0 } } process { # Write an empty line to the console (placeholder or for spacing purposes) Write-Host -Object "" # Check if the script is running with elevated (administrator) privileges if (!(Test-IsElevated)) { Write-Host -Object "[Error] Access Denied. Please run with Administrator privileges." exit 1 } # Check if the current device is either joined to a domain or is a domain controller if(Test-IsDomainJoined -or Test-IsDomainController){ # Display a warning indicating that the device is joined to a domain Write-Host -Object "[Warning] This device is currently joined to a domain. This setting can be overridden by a group policy." # Display additional information about the group policy that can override the setting Write-Host -Object "[Warning] Computer Configuration > Administrative Templates > Windows Components > Windows Update > Remove access to use all Windows Update features." } # If the action is "Enable" and the specified registry path exists if ($Action -eq "Enable" -and (Test-Path -Path "Registry::HKEY_LOCAL_MACHINE\Software\Policies\Microsoft\Windows\WindowsUpdate" -ErrorAction SilentlyContinue)) { try { # Attempt to retrieve the existing value for "SetDisableUXWUAccess" from the registry $ExistingValue = Get-ItemProperty -Path "Registry::HKEY_LOCAL_MACHINE\Software\Policies\Microsoft\Windows\WindowsUpdate" -ErrorAction Stop | Select-Object -ExpandProperty "SetDisableUXWUAccess" -ErrorAction SilentlyContinue } catch { # Display an error message if retrieval fails and exit the script Write-Host -Object "[Error] $($_.Exception.Message)" Write-Host -Object "[Error] Failed to retrieve the existing 'Check for Updates' value." exit 1 } } # Check if the action is "Enable" if ($Action -eq "Enable") { Write-Host -Object "Attempting to enable the 'Check for Updates' button." # If the registry value does not exist or is empty, the button is already enabled if (!$ExistingValue) { Write-Host -Object "Registry::HKEY_LOCAL_MACHINE\Software\Policies\Microsoft\Windows\WindowsUpdate\SetDisableUXWUAccess was already removed." } # If the registry value exists, attempt to remove it to enable the button if ($ExistingValue) { try { # Remove the "SetDisableUXWUAccess" property from the registry Remove-ItemProperty -Path "Registry::HKEY_LOCAL_MACHINE\Software\Policies\Microsoft\Windows\WindowsUpdate" -Name "SetDisableUXWUAccess" -ErrorAction Stop Write-Host -Object "Removed the registry key 'Registry::HKEY_LOCAL_MACHINE\Software\Policies\Microsoft\Windows\WindowsUpdate\SetDisableUXWUAccess'." } catch { # Display an error message if removal fails and exit the script Write-Host -Object "[Error] $($_.Exception.Message)" Write-Host -Object "[Error] Failed to enable the 'Check for Updates' button." exit 1 } } # Indicate success and exit the script Write-Host -Object "Successfully enabled the 'Check for Updates' button." exit $ExitCode } # Check if the action is "Disable" if ($Action -eq "Disable") { Write-Host -Object "Attempting to disable the 'Check for Updates' button." # Add or update the "SetDisableUXWUAccess" property in the registry to disable the button Set-RegKey -Path "Registry::HKEY_LOCAL_MACHINE\Software\Policies\Microsoft\Windows\WindowsUpdate" -Name "SetDisableUXWUAccess" -Value 1 -PropertyType DWord # Indicate success Write-Host -Object "Successfully disabled the 'Check for Updates' button." } exit $ExitCode } end { }
Detailed Breakdown
Let’s walk through what this script actually does.
Step 1: Input Validation
The script accepts a single parameter: -Action, which must be either “Enable” or “Disable”. It validates the input and provides user-friendly error messages if the action is missing or invalid.
It also supports running in script form by checking for the action environment variable—useful in automated tools or deployment pipelines.
Step 2: Permissions and Domain Checks
Before making any changes, the script checks:
- If it’s running with administrator privileges
- Whether the machine is domain-joined or a domain controller
This is important because domain group policies can override registry settings, rendering local changes ineffective.
Step 3: Enable or Disable the Button
The functionality hinges on one registry key:
CopyEdit
HKEY_LOCAL_MACHINE\Software\Policies\Microsoft\Windows\WindowsUpdate\SetDisableUXWUAccess
- To Disable: The script sets the key’s value to 1, which hides or disables the “Check for Updates” button.
- To Enable: It removes the key entirely, restoring the button.
Supporting Functions
The script uses helper functions to:
- Create or modify registry keys (Set-RegKey)
- Determine if the session is elevated
- Test if the system is domain-joined or a domain controller
These modular functions improve clarity and reusability, a hallmark of good scripting practices.
Potential Use Cases
Case Study: A Managed Service Provider
An MSP managing 150 Windows 10 devices for a client needs to freeze manual updates during a critical application rollout. They deploy this script through their RMM tool with the -Action “Disable” parameter. Users no longer see the “Check for Updates” button, ensuring updates don’t interrupt installations. Once the rollout is stable, they run the script again with -Action “Enable” to restore access.
Comparisons
While Group Policy provides a long-standing method to control update access, it requires Active Directory. In contrast, this PowerShell script works on standalone machines, making it perfect for:
- BYOD environments
- Remote laptops not joined to a domain
- MSP-managed clients with decentralized infrastructure
Other methods like local policy editors (gpedit.msc) require manual configuration per machine and lack scalability.
FAQs
Q: Does this script work on Windows 11?
Yes, as long as the registry structure remains the same. However, always validate in a test environment.
Q: Will this script prevent automatic updates?
No. It only disables the user’s ability to manually check for updates. Windows Update services will still function based on system policy.
Q: Can domain policies override this setting?
Yes. If a Group Policy is configured to manage update settings, it may override local registry changes.
Q: Is a restart required?
No reboot is required. The change takes effect immediately in the Windows Update UI.
Implications
Controlling the “Check for Updates” button has broad implications for patch management. While disabling it enhances control and standardization, it also places the onus on IT teams to ensure timely updates. Used improperly, it can delay critical patches and increase security risks.
This underscores the importance of aligning script usage with robust patching policies and communication with stakeholders.
Recommendations
- Always test the script in a staging environment before wide deployment.
- Use logging to capture results for auditing purposes.
- Pair this script with monitoring to ensure updates are still applied through approved channels.
- Document policy exceptions where user update access is restored.
Final Thoughts
Automating Windows Update controls is a smart move for modern IT departments, especially those managing hybrid or decentralized environments. This PowerShell script to disable or enable the Check for Updates button gives IT professionals flexible control without relying solely on Group Policy.
When paired with a robust RMM platform like NinjaOne, this script becomes even more powerful. NinjaOne allows automated, policy-based deployment of scripts across devices, provides audit trails, and integrates seamlessly with patch management workflows. For IT teams looking to balance control with agility, combining this script with NinjaOne’s automation can lead to smarter, more secure device management.