Skip to content

Instantly share code, notes, and snippets.

@InTEGr8or
Last active September 5, 2026 20:45
Show Gist options
  • Select an option

  • Save InTEGr8or/1bc0f00a4bb7d4e67e391d19c3076192 to your computer and use it in GitHub Desktop.

Select an option

Save InTEGr8or/1bc0f00a4bb7d4e67e391d19c3076192 to your computer and use it in GitHub Desktop.
Prevent Windows from silently auto-updating WSL and killing running microVMs
<#
.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