@@ -37,8 +37,19 @@ function Fetch-File {
3737# version/list matches fail unless the NULs are stripped first.
3838function Get-WslText {
3939 param ([Parameter (Mandatory = $true )][string []]$ArgumentList )
40- $raw = & $wsl @ArgumentList 2>&1 | Out-String
41- $code = $LASTEXITCODE
40+ # Windows PowerShell promotes native stderr to ErrorRecord objects. With the
41+ # script-wide Stop policy, an expected nonzero probe (such as --version on a
42+ # genuinely fresh host) otherwise aborts before we can inspect LASTEXITCODE
43+ # and install WSL. Keep the probe non-terminating, then restore fail-closed
44+ # behavior for the surrounding setup transaction.
45+ $previousErrorAction = $ErrorActionPreference
46+ try {
47+ $ErrorActionPreference = " Continue"
48+ $raw = & $wsl @ArgumentList 2>&1 | Out-String
49+ $code = $LASTEXITCODE
50+ } finally {
51+ $ErrorActionPreference = $previousErrorAction
52+ }
4253 $text = ($raw -replace [char ]0 , " " ).Trim()
4354 return [pscustomobject ]@ { ExitCode = $code ; Text = $text }
4455}
@@ -103,63 +114,69 @@ function Fail-Setup {
103114}
104115
105116if ($HostSetup ) {
106- $identity = [Security.Principal.WindowsIdentity ]::GetCurrent()
107- $principal = [Security.Principal.WindowsPrincipal ]::new($identity )
108- if (-not $principal.IsInRole ([Security.Principal.WindowsBuiltInRole ]::Administrator)) {
109- Fail- Setup " The WSL host setup phase requires administrator approval."
110- }
111- Write-SetupStatus - Status " running" - Step " Enabling Windows WSL features..." - Progress 8
112- $wslFeature = Get-WindowsOptionalFeature - Online - FeatureName Microsoft- Windows- Subsystem- Linux
113- $vmFeature = Get-WindowsOptionalFeature - Online - FeatureName VirtualMachinePlatform
114- if ($wslFeature.State -ne " Enabled" ) { Enable-WindowsOptionalFeature - Online - FeatureName Microsoft- Windows- Subsystem- Linux - All - NoRestart | Out-Null }
115- if ($vmFeature.State -ne " Enabled" ) { Enable-WindowsOptionalFeature - Online - FeatureName VirtualMachinePlatform - All - NoRestart | Out-Null }
116- $wslFeature = Get-WindowsOptionalFeature - Online - FeatureName Microsoft- Windows- Subsystem- Linux
117- $vmFeature = Get-WindowsOptionalFeature - Online - FeatureName VirtualMachinePlatform
118- $restartRequired = (Test-RestartRequired $wslFeature ) -or (Test-RestartRequired $vmFeature )
119- $hostTemporary = Join-Path ([System.IO.Path ]::GetTempPath()) (" 1helm-wsl-host-" + [Guid ]::NewGuid().ToString(" N" ))
120- New-Item - ItemType Directory - Path $hostTemporary | Out-Null
121117 try {
122- if (-not (Test-PinnedWslRuntime )) {
123- $msi = Join-Path $hostTemporary " wsl.candidate.msi"
124- Write-SetupStatus - Status " running" - Step " Downloading Microsoft WSL installer..." - Progress 12
125- Fetch- File - Url $wslInstallerUrl - Destination $msi
126- if ((Get-FileHash - LiteralPath $msi - Algorithm SHA256).Hash.ToLowerInvariant() -ne $wslInstallerSha256 ) {
127- Fail- Setup " Microsoft WSL installer did not match 1Helm's pinned SHA-256."
128- }
129- $signature = Get-AuthenticodeSignature - LiteralPath $msi
130- if ($signature.Status -ne [System.Management.Automation.SignatureStatus ]::Valid -or $null -eq $signature.SignerCertificate -or
131- $signature.SignerCertificate.Subject -notmatch ' (^|,\s*)CN=Microsoft Corporation(,|$)' ) {
132- Fail- Setup " Microsoft WSL installer did not have a valid Microsoft Corporation signature."
133- }
134- Write-SetupStatus - Status " running" - Step " Installing Microsoft WSL $wslVersion ..." - Progress 18
135- $installer = Start-Process - FilePath " $env: SystemRoot \System32\msiexec.exe" - ArgumentList @ (" /i" , $msi , " /qn" , " /norestart" ) - Wait - PassThru
136- # 0 success; 1641/3010 success+reboot; 1638 already installed (same/newer).
137- # 1603 is a hard fail from msiexec, but on machines that already have the
138- # pinned WSL build (or UTF-16 made detection fail earlier) the package may
139- # still leave a working runtime - re-verify before failing closed.
140- if ($installer.ExitCode -in @ (1641 , 3010 )) { $restartRequired = $true }
141- elseif ($installer.ExitCode -notin @ (0 , 1638 )) {
142- if (Test-PinnedWslRuntime ) {
143- Write-Host " Microsoft WSL installer returned $ ( $installer.ExitCode ) , but pinned WSL $wslVersion is already present; continuing."
144- } else {
145- Fail- Setup " Microsoft WSL installer failed with exit code $ ( $installer.ExitCode ) ."
118+ $identity = [Security.Principal.WindowsIdentity ]::GetCurrent()
119+ $principal = [Security.Principal.WindowsPrincipal ]::new($identity )
120+ if (-not $principal.IsInRole ([Security.Principal.WindowsBuiltInRole ]::Administrator)) {
121+ Fail- Setup " The WSL host setup phase requires administrator approval."
122+ }
123+ Write-SetupStatus - Status " running" - Step " Enabling Windows WSL features..." - Progress 8
124+ $wslFeature = Get-WindowsOptionalFeature - Online - FeatureName Microsoft- Windows- Subsystem- Linux
125+ $vmFeature = Get-WindowsOptionalFeature - Online - FeatureName VirtualMachinePlatform
126+ if ($wslFeature.State -ne " Enabled" ) { Enable-WindowsOptionalFeature - Online - FeatureName Microsoft- Windows- Subsystem- Linux - All - NoRestart | Out-Null }
127+ if ($vmFeature.State -ne " Enabled" ) { Enable-WindowsOptionalFeature - Online - FeatureName VirtualMachinePlatform - All - NoRestart | Out-Null }
128+ $wslFeature = Get-WindowsOptionalFeature - Online - FeatureName Microsoft- Windows- Subsystem- Linux
129+ $vmFeature = Get-WindowsOptionalFeature - Online - FeatureName VirtualMachinePlatform
130+ $restartRequired = (Test-RestartRequired $wslFeature ) -or (Test-RestartRequired $vmFeature )
131+ $hostTemporary = Join-Path ([System.IO.Path ]::GetTempPath()) (" 1helm-wsl-host-" + [Guid ]::NewGuid().ToString(" N" ))
132+ New-Item - ItemType Directory - Path $hostTemporary | Out-Null
133+ try {
134+ if (-not (Test-PinnedWslRuntime )) {
135+ $msi = Join-Path $hostTemporary " wsl.candidate.msi"
136+ Write-SetupStatus - Status " running" - Step " Downloading Microsoft WSL installer..." - Progress 12
137+ Fetch- File - Url $wslInstallerUrl - Destination $msi
138+ if ((Get-FileHash - LiteralPath $msi - Algorithm SHA256).Hash.ToLowerInvariant() -ne $wslInstallerSha256 ) {
139+ Fail- Setup " Microsoft WSL installer did not match 1Helm's pinned SHA-256."
146140 }
141+ $signature = Get-AuthenticodeSignature - LiteralPath $msi
142+ if ($signature.Status -ne [System.Management.Automation.SignatureStatus ]::Valid -or $null -eq $signature.SignerCertificate -or
143+ $signature.SignerCertificate.Subject -notmatch ' (^|,\s*)CN=Microsoft Corporation(,|$)' ) {
144+ Fail- Setup " Microsoft WSL installer did not have a valid Microsoft Corporation signature."
145+ }
146+ Write-SetupStatus - Status " running" - Step " Installing Microsoft WSL $wslVersion ..." - Progress 18
147+ $installer = Start-Process - FilePath " $env: SystemRoot \System32\msiexec.exe" - ArgumentList @ (" /i" , $msi , " /qn" , " /norestart" ) - Wait - PassThru
148+ # 0 success; 1641/3010 success+reboot; 1638 already installed (same/newer).
149+ # 1603 is a hard fail from msiexec, but on machines that already have the
150+ # pinned WSL build (or UTF-16 made detection fail earlier) the package may
151+ # still leave a working runtime - re-verify before failing closed.
152+ if ($installer.ExitCode -in @ (1641 , 3010 )) { $restartRequired = $true }
153+ elseif ($installer.ExitCode -notin @ (0 , 1638 )) {
154+ if (Test-PinnedWslRuntime ) {
155+ Write-Host " Microsoft WSL installer returned $ ( $installer.ExitCode ) , but pinned WSL $wslVersion is already present; continuing."
156+ } else {
157+ Fail- Setup " Microsoft WSL installer failed with exit code $ ( $installer.ExitCode ) ."
158+ }
159+ }
160+ } else {
161+ Write-SetupStatus - Status " running" - Step " Microsoft WSL $wslVersion is already installed." - Progress 18
147162 }
148- } else {
149- Write-SetupStatus - Status " running" - Step " Microsoft WSL $wslVersion is already installed." - Progress 18
150- }
151- if ($restartRequired ) {
152- Write-SetupStatus - Status " restart_required" - Step " WSL 2 features are enabled. Restart Windows once, then retry 1Helm computer setup." - Progress 20
153- exit 10
163+ if ($restartRequired ) {
164+ Write-SetupStatus - Status " restart_required" - Step " WSL 2 features are enabled. Restart Windows once, then retry 1Helm computer setup." - Progress 20
165+ exit 10
166+ }
167+ if (-not (Test-PinnedWslRuntime )) { Fail- Setup " Microsoft WSL $wslVersion was installed but could not be verified." }
168+ Write-SetupStatus - Status " running" - Step " Setting WSL 2 as the default..." - Progress 22
169+ $defaultVersion = Get-WslText - ArgumentList @ (" --set-default-version" , " 2" )
170+ if ($defaultVersion.ExitCode -ne 0 ) { Fail- Setup " WSL could not set version 2 as the default. $ ( $defaultVersion.Text ) " }
171+ } finally {
172+ if (Test-Path - LiteralPath $hostTemporary ) { Remove-Item - LiteralPath $hostTemporary - Recurse - Force }
154173 }
155- if (-not (Test-PinnedWslRuntime )) { Fail- Setup " Microsoft WSL $wslVersion was installed but could not be verified." }
156- Write-SetupStatus - Status " running" - Step " Setting WSL 2 as the default..." - Progress 22
157- $defaultVersion = Get-WslText - ArgumentList @ (" --set-default-version" , " 2" )
158- if ($defaultVersion.ExitCode -ne 0 ) { Fail- Setup " WSL could not set version 2 as the default. $ ( $defaultVersion.Text ) " }
159- } finally {
160- if (Test-Path - LiteralPath $hostTemporary ) { Remove-Item - LiteralPath $hostTemporary - Recurse - Force }
174+ exit 0
175+ } catch {
176+ $message = $_.Exception.Message
177+ if (-not $message ) { $message = " $_ " }
178+ Fail- Setup $message
161179 }
162- exit 0
163180}
164181
165182# Keep the distribution owned by the signed-in Windows account. Only optional
0 commit comments