Last active
September 5, 2026 20:45
-
-
Save InTEGr8or/1bc0f00a4bb7d4e67e391d19c3076192 to your computer and use it in GitHub Desktop.
Prevent Windows from silently auto-updating WSL and killing running microVMs
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| <# | |
| .SYNOPSIS | |
| Prevents Windows from silently auto-updating Windows Subsystem for Linux (WSL) | |
| and abruptly terminating running microVM instances and active developer sessions. | |
| .DESCRIPTION | |
| By default in modern Windows 11 builds, WSL is classified as a "System Component" | |
| managed by Microsoft Update and Microsoft Store. When an update is deployed, | |
| the Windows RestartManager forcefully kills vmwp.exe and wslhost.exe to replace | |
| binaries, dropping all running containers, distros, and background jobs. | |
| This script disables background automatic updates for Store packages and opts | |
| out of background Microsoft Product updates, ensuring WSL only updates when | |
| explicitly triggered by the user (e.g., via 'wsl --update'). | |
| .PARAMETER ConfigureWindowsUpdateNotify | |
| Optional. If specified, sets Windows Update to notify before downloading/installing | |
| core OS updates, and prevents automatic restarts while users are logged on. | |
| .PARAMETER PinWinget | |
| Pins the 'Microsoft.WSL' package in winget with --blocking so automated | |
| package upgrades ('winget upgrade --all') do not touch WSL. Defaults to $true. | |
| .EXAMPLE | |
| .\Prevent-WSLSilentUpdates.ps1 | |
| Applies the targeted WSL and Store auto-update blocks. | |
| .EXAMPLE | |
| .\Prevent-WSLSilentUpdates.ps1 -ConfigureWindowsUpdateNotify | |
| Applies the WSL blocks and also switches OS updates to notify-only. | |
| #> | |
| [CmdletBinding(SupportsShouldProcess)] | |
| param( | |
| [switch]$ConfigureWindowsUpdateNotify, | |
| [bool]$PinWinget = $true | |
| ) | |
| # 1. Require Administrator privileges | |
| $isAdmin = ([Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole( | |
| [Security.Principal.WindowsBuiltInRole]::Administrator | |
| ) | |
| if (-not $isAdmin) { | |
| Write-Error "This script requires Administrator privileges. Please re-run from an elevated PowerShell prompt." | |
| exit 1 | |
| } | |
| function Set-RegistryValueSafely { | |
| param( | |
| [Parameter(Mandatory)] [string]$Path, | |
| [Parameter(Mandatory)] [string]$Name, | |
| [Parameter(Mandatory)] $Value, | |
| [string]$Type = "DWord", | |
| [string]$Description = "" | |
| ) | |
| if (-not (Test-Path $Path)) { | |
| New-Item -Path $Path -Force | Out-Null | |
| } | |
| Set-ItemProperty -Path $Path -Name $Name -Value $Value -Type $Type -Force | |
| Write-Host "[OK] $Description ($Path\$Name = $Value)" -ForegroundColor Green | |
| } | |
| Write-Host "=== Hardening WSL Against Spontaneous Auto-Update Termination ===" -ForegroundColor Cyan | |
| # 2. Permanently disable Microsoft Store background auto-updates (Group Policy override) | |
| # AutoDownload values: 2 = Disable automatic download and install, 4 = Auto-download | |
| Set-RegistryValueSafely ` | |
| -Path "HKLM:\SOFTWARE\Policies\Microsoft\WindowsStore" ` | |
| -Name "AutoDownload" ` | |
| -Value 2 ` | |
| -Description "Disabled Microsoft Store automatic app updates (policy override)" | |
| # 3. Disable 'Receive updates for other Microsoft products' (which includes WSL) | |
| Set-RegistryValueSafely ` | |
| -Path "HKLM:\SOFTWARE\Microsoft\WindowsUpdate\UX\Settings" ` | |
| -Name "AllowMUUpdateService" ` | |
| -Value 0 ` | |
| -Description "Turned off 'Receive updates for other Microsoft products' (UX Settings)" | |
| Set-RegistryValueSafely ` | |
| -Path "HKLM:\SOFTWARE\Microsoft\WindowsUpdate\UX\Settings" ` | |
| -Name "IsContinuousInnovationOptedIn" ` | |
| -Value 0 ` | |
| -Description "Turned off 'Get latest updates as soon as available' (Continuous Innovation)" | |
| Set-RegistryValueSafely ` | |
| -Path "HKLM:\SOFTWARE\Policies\Microsoft\Windows\WindowsUpdate\AU" ` | |
| -Name "AllowMUUpdateService" ` | |
| -Value 0 ` | |
| -Description "Turned off Microsoft Update service via Group Policy" | |
| # Unregister Microsoft Update service from Windows Update COM manager if present | |
| try { | |
| $serviceManager = New-Object -ComObject Microsoft.Update.ServiceManager -ErrorAction Stop | |
| $serviceManager.ClientApplicationID = "Prevent-WSLSilentUpdates" | |
| $muService = $serviceManager.Services | Where-Object { $_.ServiceID -eq "7971f918-a847-4430-9279-4a52d1efe18d" } | |
| if ($muService) { | |
| $serviceManager.RemoveService("7971f918-a847-4430-9279-4a52d1efe18d") | |
| Write-Host "[OK] Unregistered Microsoft Update service COM provider" -ForegroundColor Green | |
| } | |
| } catch { | |
| Write-Verbose "Could not query Microsoft.Update.ServiceManager COM object: $_" | |
| } | |
| # 4. Pin WSL in winget to prevent 'winget upgrade --all' from upgrading it | |
| if ($PinWinget) { | |
| if (Get-Command winget -ErrorAction SilentlyContinue) { | |
| Write-Host "[*] Pinning Microsoft.WSL in winget..." -ForegroundColor Yellow | |
| winget pin add --id Microsoft.WSL --blocking 2>$null | |
| Write-Host "[OK] Pinned Microsoft.WSL in winget" -ForegroundColor Green | |
| } | |
| } | |
| # 5. Optional: Configure Windows Update to notify before download/install | |
| if ($ConfigureWindowsUpdateNotify) { | |
| # AUOptions: 2 = Notify for download and notify for install | |
| Set-RegistryValueSafely ` | |
| -Path "HKLM:\SOFTWARE\Policies\Microsoft\Windows\WindowsUpdate\AU" ` | |
| -Name "NoAutoUpdate" ` | |
| -Value 0 ` | |
| -Description "Enabled Windows Update configuration" | |
| Set-RegistryValueSafely ` | |
| -Path "HKLM:\SOFTWARE\Policies\Microsoft\Windows\WindowsUpdate\AU" ` | |
| -Name "AUOptions" ` | |
| -Value 2 ` | |
| -Description "Set Windows Update to notify before download and install" | |
| Set-RegistryValueSafely ` | |
| -Path "HKLM:\SOFTWARE\Policies\Microsoft\Windows\WindowsUpdate\AU" ` | |
| -Name "NoAutoRebootWithLoggedOnUsers" ` | |
| -Value 1 ` | |
| -Description "Prevented automatic reboots while users are logged on" | |
| } | |
| Write-Host "`nAll targeted protections applied successfully." -ForegroundColor Cyan | |
| Write-Host "WSL will no longer be silently updated in the background." -ForegroundColor White | |
| Write-Host "To manually update WSL in the future when convenient, run: wsl --update" -ForegroundColor Gray |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment