How to Disable or Enable the “Check for Updates” Button with PowerShell

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.

Next Steps

Building an efficient and effective IT team requires a centralized solution that acts as your core service delivery tool. NinjaOne enables IT teams to monitor, manage, secure, and support all their devices, wherever they are, without the need for complex on-premises infrastructure.

Learn more about NinjaOne Remote Script Deployment, check out a live tour, or start your free trial of the NinjaOne platform.

Categories:

You might also like

×

See NinjaOne in action!

By submitting this form, I accept NinjaOne's privacy policy.

NinjaOne Terms & Conditions

By clicking the “I Accept” button below, you indicate your acceptance of the following legal terms as well as our 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 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).