@@ -66,6 +66,18 @@ function Test-RestartRequired {
6666 return $value -eq " Required" -or $value -eq " 1" -or $value -eq " True"
6767}
6868
69+ function Test-WslRestartFailure {
70+ param ([string ]$Text )
71+ return $Text -match ' HCS_E_SERVICE_NOT_AVAILABLE|required feature is not installed'
72+ }
73+
74+ function Require-WindowsRestart {
75+ $message = " WSL 2 features are enabled. Restart Windows once, then retry 1Helm computer setup."
76+ Write-SetupStatus - Status " restart_required" - Step $message - Progress 20 - ErrorMessage " Windows restart required to finish enabling WSL 2."
77+ Write-Host $message
78+ exit 10
79+ }
80+
6981function Get-WslDistributionNames {
7082 $result = Get-WslText - ArgumentList @ (" --list" , " --quiet" )
7183 if ($result.ExitCode -ne 0 ) { return @ () }
@@ -123,11 +135,16 @@ if ($HostSetup) {
123135 Write-SetupStatus - Status " running" - Step " Enabling Windows WSL features..." - Progress 8
124136 $wslFeature = Get-WindowsOptionalFeature - Online - FeatureName Microsoft- Windows- Subsystem- Linux
125137 $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 }
138+ $enabledWslFeatureNow = $wslFeature.State -ne " Enabled"
139+ $enabledVmFeatureNow = $vmFeature.State -ne " Enabled"
140+ if ($enabledWslFeatureNow ) { Enable-WindowsOptionalFeature - Online - FeatureName Microsoft- Windows- Subsystem- Linux - All - NoRestart | Out-Null }
141+ if ($enabledVmFeatureNow ) { Enable-WindowsOptionalFeature - Online - FeatureName VirtualMachinePlatform - All - NoRestart | Out-Null }
128142 $wslFeature = Get-WindowsOptionalFeature - Online - FeatureName Microsoft- Windows- Subsystem- Linux
129143 $vmFeature = Get-WindowsOptionalFeature - Online - FeatureName VirtualMachinePlatform
130- $restartRequired = (Test-RestartRequired $wslFeature ) -or (Test-RestartRequired $vmFeature )
144+ # DISM's RestartRequired enum can stringify as "Possible" even though its
145+ # numeric value is 1. Enabling either feature in this invocation is itself
146+ # authoritative evidence that Windows must reboot before a WSL 2 VM import.
147+ $restartRequired = $enabledWslFeatureNow -or $enabledVmFeatureNow -or (Test-RestartRequired $wslFeature ) -or (Test-RestartRequired $vmFeature )
131148 $hostTemporary = Join-Path ([System.IO.Path ]::GetTempPath()) (" 1helm-wsl-host-" + [Guid ]::NewGuid().ToString(" N" ))
132149 New-Item - ItemType Directory - Path $hostTemporary | Out-Null
133150 try {
@@ -160,14 +177,20 @@ if ($HostSetup) {
160177 } else {
161178 Write-SetupStatus - Status " running" - Step " Microsoft WSL $wslVersion is already installed." - Progress 18
162179 }
180+ # A feature may already report Enabled before the reboot has registered
181+ # WSL's VM compute service. This is the concrete pre-reboot state that
182+ # otherwise lets setup continue into HCS_E_SERVICE_NOT_AVAILABLE.
183+ if ($null -eq (Get-Service - Name vmcompute - ErrorAction SilentlyContinue)) { $restartRequired = $true }
163184 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
185+ Require- WindowsRestart
166186 }
167187 if (-not (Test-PinnedWslRuntime )) { Fail- Setup " Microsoft WSL $wslVersion was installed but could not be verified." }
168188 Write-SetupStatus - Status " running" - Step " Setting WSL 2 as the default..." - Progress 22
169189 $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 ) " }
190+ if ($defaultVersion.ExitCode -ne 0 ) {
191+ if (Test-WslRestartFailure $defaultVersion.Text ) { Require- WindowsRestart }
192+ Fail- Setup " WSL could not set version 2 as the default. $ ( $defaultVersion.Text ) "
193+ }
171194 } finally {
172195 if (Test-Path - LiteralPath $hostTemporary ) { Remove-Item - LiteralPath $hostTemporary - Recurse - Force }
173196 }
@@ -242,11 +265,22 @@ try {
242265 $names = @ (Get-WslDistributionNames )
243266 $runtimeRoot = Join-Path $env: LOCALAPPDATA " 1Helm-Runtime"
244267 $installDirectory = Join-Path $runtimeRoot $RuntimeName
268+ $partialMarker = " $installDirectory .1helm-partial-import"
245269 if ($names -notcontains $RuntimeName ) {
246270 if (Test-Path - LiteralPath $installDirectory ) {
247- Fail- Setup " The shared runtime disk directory already exists without a registered runtime. Remove `" $installDirectory `" or unregister the partial distro, then retry."
271+ $entries = @ (Get-ChildItem - LiteralPath $installDirectory - Force - ErrorAction SilentlyContinue)
272+ $ownedPartial = (Test-Path - LiteralPath $partialMarker - PathType Leaf) -and ((Get-Content - LiteralPath $partialMarker - Raw).Trim() -eq $RuntimeName )
273+ # v0.0.33 could leave an empty app-owned directory when Windows rejected
274+ # the import before creating its VM. New attempts carry an ownership
275+ # marker so an interrupted partial VHD can also be retried safely.
276+ if ($entries.Count -eq 0 -or $ownedPartial ) {
277+ Remove-Item - LiteralPath $installDirectory - Recurse - Force
278+ } else {
279+ Fail- Setup " The shared runtime disk directory already exists without a registered runtime. Remove `" $installDirectory `" or unregister the partial distro, then retry."
280+ }
248281 }
249282 New-Item - ItemType Directory - Path $installDirectory - Force | Out-Null
283+ [System.IO.File ]::WriteAllText($partialMarker , $RuntimeName , [System.Text.UTF8Encoding ]::new($false ))
250284 $rootfs = Join-Path $temporary " ubuntu-noble-wsl.rootfs.tar.gz"
251285 Write-SetupStatus - Status " running" - Step " Downloading shared Linux runtime base..." - Progress 35
252286 Fetch- File - Url $rootfsUrl - Destination $rootfs
@@ -255,7 +289,11 @@ try {
255289 }
256290 Write-SetupStatus - Status " running" - Step " Importing shared Linux runtime..." - Progress 48
257291 $imported = Get-WslText - ArgumentList @ (" --import" , $RuntimeName , $installDirectory , $rootfs , " --version" , " 2" )
258- if ($imported.ExitCode -ne 0 ) { Fail- Setup " The shared 1Helm WSL runtime could not be imported. $ ( $imported.Text ) " }
292+ if ($imported.ExitCode -ne 0 ) {
293+ if (Test-WslRestartFailure $imported.Text ) { Require- WindowsRestart }
294+ Fail- Setup " The shared 1Helm WSL runtime could not be imported. $ ( $imported.Text ) "
295+ }
296+ Remove-Item - LiteralPath $partialMarker - Force
259297 }
260298
261299 Write-SetupStatus - Status " running" - Step " Installing shared runtime packages (podman, crun, ...)..." - Progress 58
0 commit comments