Last active
October 13, 2025 23:03
-
-
Save emilwojcik93/6f337453a482f15dde4959d0b032ae0e to your computer and use it in GitHub Desktop.
Automatically detects and fixes WSL Interop naming conflict (WSLInterop-late vs WSLInterop) in Ubuntu-family distributions. Version 2.0 with clean console output, wslpath integration, and reliable service installation.
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 | |
| Automatically detects and fixes WSL Interop naming conflict issue (WSLInterop-late vs WSLInterop) in Ubuntu-family WSL distributions. | |
| .DESCRIPTION | |
| This script identifies the systemd-binfmt vs wslu naming conflict in WSL Ubuntu-family distributions (Ubuntu 24.04+) | |
| and automatically installs a permanent systemd service fix. Only works with Ubuntu/Debian-based distributions that use apt and systemd. | |
| Issue: https://github.com/microsoft/WSL/issues/13449 | |
| .PARAMETER Verbose | |
| Enables detailed output during execution. | |
| .EXAMPLE | |
| # Run directly from GitHub Gist | |
| &([ScriptBlock]::Create((irm https://gist.githubusercontent.com/emilwojcik93/6f337453a482f15dde4959d0b032ae0e/raw/Fix-WSLInterop.ps1))) -Verbose | |
| .NOTES | |
| Author: emilwojcik93 | |
| Version: 2.0 - Improved version with clean console output and reliable service installation | |
| Requires: Windows 10/11 with WSL 2, Ubuntu-family distribution (Ubuntu/Debian with apt and systemd) | |
| GitHub Issue: https://github.com/microsoft/WSL/issues/13449 | |
| This version uses file copy method and wslpath for reliable service creation. | |
| Fixes console corruption issues from v1.0 by avoiding here-strings and complex escaping. | |
| Improvements in v2.0: | |
| - Uses wslpath for proper Windows-to-Unix path conversion | |
| - Creates service file in Windows temp directory, copies to WSL | |
| - Simple output functions prevent console corruption | |
| - Reliable systemd service installation without escaping issues | |
| - Silent apt installation to reduce output noise | |
| Supported Distributions: Ubuntu 24.04+, Ubuntu derivatives, Debian with systemd | |
| #> | |
| [CmdletBinding()] | |
| param() | |
| $ErrorActionPreference = 'Continue' | |
| $ProgressPreference = 'SilentlyContinue' | |
| # Simple output functions without color to avoid console issues | |
| function Write-Info { param($msg) Write-Output "[INFO] $msg" } | |
| function Write-Success { param($msg) Write-Output "[SUCCESS] $msg" } | |
| function Write-Warn { param($msg) Write-Warning "[WARNING] $msg" } | |
| function Write-Err { param($msg) Write-Error "[ERROR] $msg" -ErrorAction Continue } | |
| Write-Output "WSL Interop Issue Auto-Fix Script v2.0" | |
| Write-Output "======================================" | |
| Write-Output "GitHub Issue: https://github.com/microsoft/WSL/issues/13449" | |
| Write-Output "" | |
| # Check WSL installation | |
| Write-Info "Checking WSL installation..." | |
| $wslExe = Get-Command wsl.exe -ErrorAction SilentlyContinue | |
| if (-not $wslExe) { | |
| Write-Err "wsl.exe not found. Please install WSL first." | |
| exit 1 | |
| } | |
| # Check WSL distributions from registry | |
| $lxssPath = "HKCU:\SOFTWARE\Microsoft\Windows\CurrentVersion\Lxss" | |
| if (-not (Test-Path $lxssPath)) { | |
| Write-Err "No WSL distributions found. Please install Ubuntu." | |
| Write-Output "Run: wsl --install -d Ubuntu" | |
| exit 1 | |
| } | |
| # Get default distribution | |
| $distributions = Get-ChildItem -Path $lxssPath -ErrorAction SilentlyContinue | |
| $defaultDistro = $null | |
| $defaultGuid = Get-ItemProperty -Path $lxssPath -Name "DefaultDistribution" -ErrorAction SilentlyContinue | |
| foreach ($distro in $distributions) { | |
| $props = Get-ItemProperty -Path $distro.PSPath -ErrorAction SilentlyContinue | |
| if ($props.DistributionName -and ($distro.PSChildName -eq $defaultGuid.DefaultDistribution)) { | |
| $defaultDistro = $props.DistributionName | |
| break | |
| } | |
| } | |
| if (-not $defaultDistro) { | |
| $firstDistro = Get-ItemProperty -Path $distributions[0].PSPath -ErrorAction SilentlyContinue | |
| $defaultDistro = $firstDistro.DistributionName | |
| } | |
| Write-Success "Found WSL distribution: $defaultDistro" | |
| # Check if it's Ubuntu-family | |
| Write-Info "Verifying Ubuntu-family distribution..." | |
| $ubuntuCheck = wsl -d $defaultDistro -u root -e bash -c "command -v apt && command -v systemctl" 2>$null | |
| if ($LASTEXITCODE -ne 0) { | |
| Write-Err "Distribution '$defaultDistro' is not Ubuntu-family (missing apt or systemd)" | |
| Write-Output "This script only works with Ubuntu/Debian-based distributions" | |
| Write-Output "" | |
| Write-Output "Alternative methods (work on any distribution):" | |
| Write-Output "wsl bash -c `"powershell.exe -Command '\`$env:UserProfile' | tr -d '\r'`"" | |
| exit 1 | |
| } | |
| Write-Success "Ubuntu-family distribution confirmed" | |
| # Check for interop issue | |
| Write-Info "Checking for WSL Interop issue..." | |
| $wslInteropExists = wsl -d $defaultDistro -u root -e bash -c "test -f /proc/sys/fs/binfmt_misc/WSLInterop && echo 'true' || echo 'false'" 2>$null | |
| $wslInteropLateExists = wsl -d $defaultDistro -u root -e bash -c "test -f /proc/sys/fs/binfmt_misc/WSLInterop-late && echo 'true' || echo 'false'" 2>$null | |
| if ($wslInteropExists.Trim() -eq 'true') { | |
| Write-Success "No WSL Interop issue detected - WSLInterop handler exists" | |
| exit 0 | |
| } | |
| if ($wslInteropLateExists.Trim() -ne 'true') { | |
| Write-Success "No WSL Interop issue detected - systemd not using WSLInterop-late" | |
| exit 0 | |
| } | |
| Write-Warn "WSL Interop issue detected: WSLInterop-late exists but WSLInterop missing" | |
| # Install wslu if needed | |
| Write-Info "Checking wslu installation..." | |
| $wsluInstalled = wsl -d $defaultDistro -u root -e bash -c "command -v wslvar && echo 'installed' || echo 'missing'" 2>$null | |
| if ($wsluInstalled.Trim() -ne 'installed') { | |
| Write-Info "Installing wslu package..." | |
| wsl -d $defaultDistro -u root -e bash -c "DEBIAN_FRONTEND=noninteractive apt update -qq && apt install -y wslu -qq" >$null 2>&1 | |
| if ($LASTEXITCODE -eq 0) { | |
| Write-Success "wslu package installed" | |
| } else { | |
| Write-Warn "wslu installation may have failed" | |
| } | |
| } | |
| # Create systemd service using file copy (avoids all escaping issues) | |
| Write-Info "Creating permanent systemd service fix..." | |
| # Create service file in Windows temp directory | |
| $tempServiceFile = "$env:TEMP\wsl-interop-fix.service" | |
| $serviceContent = @" | |
| [Unit] | |
| Description=Fix WSL Interop naming conflict for wslu utilities | |
| After=systemd-binfmt.service | |
| Wants=systemd-binfmt.service | |
| [Service] | |
| Type=oneshot | |
| ExecStart=/bin/bash -c 'echo ":WSLInterop:M::MZ::/init:P" | tee /proc/sys/fs/binfmt_misc/register' | |
| RemainAfterExit=yes | |
| [Install] | |
| WantedBy=multi-user.target | |
| "@ | |
| Set-Content -Path $tempServiceFile -Value $serviceContent -Encoding UTF8 | |
| # Copy service file to WSL using wslpath for proper path conversion | |
| $unixPath = wsl -d $defaultDistro -e bash -c "wslpath '$tempServiceFile'" 2>$null | |
| if ($LASTEXITCODE -ne 0 -or [string]::IsNullOrWhiteSpace($unixPath)) { | |
| Write-Err "Failed to convert Windows path to Unix path" | |
| exit 1 | |
| } | |
| $result = wsl -d $defaultDistro -u root -e bash -c "cp '$($unixPath.Trim())' /etc/systemd/system/wsl-interop-fix.service" 2>&1 | |
| if ($LASTEXITCODE -ne 0) { | |
| Write-Err "Failed to copy service file: $result" | |
| Write-Output "" | |
| Write-Output "Manual fix (temporary): wsl -u root -e bash -c `"echo ':WSLInterop:M::MZ::/init:P' | tee /proc/sys/fs/binfmt_misc/register`"" | |
| exit 1 | |
| } | |
| # Clean up temp file | |
| Remove-Item $tempServiceFile -Force -ErrorAction SilentlyContinue | |
| # Reload, enable, and start service | |
| Write-Info "Configuring systemd service..." | |
| wsl -d $defaultDistro -u root -e bash -c "systemctl daemon-reload" >$null 2>&1 | |
| $enableResult = wsl -d $defaultDistro -u root -e bash -c "systemctl enable wsl-interop-fix.service" 2>&1 | |
| wsl -d $defaultDistro -u root -e bash -c "systemctl start wsl-interop-fix.service" >$null 2>&1 | |
| # Verify service is active | |
| $serviceStatus = wsl -d $defaultDistro -u root -e bash -c "systemctl is-active wsl-interop-fix.service" 2>$null | |
| if ($serviceStatus.Trim() -eq "active") { | |
| Write-Success "WSL Interop fix service installed and running" | |
| } else { | |
| Write-Warn "Service created but may not be active (status: $serviceStatus)" | |
| } | |
| # Test the fix | |
| Write-Info "Testing the fix..." | |
| $finalTest = wsl -d $defaultDistro -u root -e bash -c "test -f /proc/sys/fs/binfmt_misc/WSLInterop && echo 'fixed' || echo 'still-broken'" 2>$null | |
| if ($finalTest.Trim() -eq 'fixed') { | |
| Write-Success "WSL Interop fix verified - WSLInterop handler now exists" | |
| # Test wslu if available | |
| $wsluTest = wsl -d $defaultDistro -e bash -c "wslvar UserProfile 2>&1" 2>$null | |
| if ($wsluTest -notmatch "WSL Interopability is disabled") { | |
| Write-Success "wslu utilities now work without errors" | |
| } | |
| } else { | |
| Write-Warn "Fix may not have applied correctly" | |
| } | |
| Write-Output "" | |
| Write-Output "Fix complete! The solution persists across WSL restarts." | |
| Write-Output "" | |
| Write-Output "Alternative methods (no system modifications needed):" | |
| Write-Output "wsl bash -c `"powershell.exe -Command '\`$env:UserProfile' | tr -d '\r'`"" | |
| Write-Output "wsl bash -c `"cmd.exe /c 'echo %USERPROFILE%' | tr -d '\r'`"" |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Thanks for your detailed GitHub issue and the workaround. Worked for my old WSL2 Ubuntu 22.04 LTS install, where I'd previously just been living with the false "WSL Interopability is disabled. Please enable it before using WSL" message.