fix(desktop): silence wsl.exe stderr banner + detached explorer relaunch rung

Follow-ups to the salvaged WSL-bridge gating (#66447):
- wsl-path-bridge.ts: discard wsl.exe stderr so the 'WSL is not installed'
  banner can never leak into an attached console on WSL-less machines (#80184).
- scripts/desktop-update/windows.ps1: add an explorer.exe-mediated detached
  relaunch rung between the WMI attempt and the tethered Start-Process
  fallback. When Win32_Process.Create fails (observed ReturnValue 8), the
  Desktop no longer re-attaches to the hand-off console, so its stdout stops
  flooding the window and the console can close.
This commit is contained in:
Teknium
2026-08-21 00:39:33 -07:00
parent deec043276
commit 0a8cdec697
2 changed files with 58 additions and 0 deletions
+53
View File
@@ -571,6 +571,59 @@ function Start-DesktopRelaunch {
} catch {
Write-HandoffLog "WARNING: WMI relaunch failed: $($_.Exception.Message); falling back"
}
if (-not $spawned) {
# Middle rung: explorer.exe-mediated launch. On some machines
# Win32_Process.Create fails outright (observed ReturnValue 8,
# "unknown failure"), and the tethered fallback below re-attaches the
# Desktop to this console — its stdout then floods the console and the
# window can't close while the app lives. Explorer re-parents the
# target exactly like a normal shell launch, giving the same
# no-console detachment WMI would have. Explorer returns no pid, so
# verify by watching for a fresh Hermes process.
try {
$exeName = [System.IO.Path]::GetFileNameWithoutExtension($RelaunchExe)
$before = @(Get-Process -Name $exeName -ErrorAction SilentlyContinue | ForEach-Object { $_.Id })
Start-Process -FilePath 'explorer.exe' -ArgumentList ('"{0}"' -f $RelaunchExe) | Out-Null
$explorerDeadline = (Get-Date).AddSeconds(15)
while ((Get-Date) -lt $explorerDeadline) {
$fresh = @(Get-Process -Name $exeName -ErrorAction SilentlyContinue | Where-Object { $before -notcontains $_.Id })
if ($fresh.Count -gt 0) {
Write-HandoffLog "desktop relaunched detached via explorer (pid $($fresh[0].Id))"
$spawned = $true
# Same foreground hand-off as the WMI rung: the new process
# starts unfocused and only the current foreground owner
# (us) can delegate that right.
try {
if ($script:Win32) {
[HermesHandoff.Win32]::AllowSetForegroundWindow([int]$fresh[0].Id) | Out-Null
$focusDeadline = (Get-Date).AddSeconds(20)
while ((Get-Date) -lt $focusDeadline) {
$hwnd = [System.IntPtr]::Zero
try { $hwnd = (Get-Process -Id $fresh[0].Id -ErrorAction Stop).MainWindowHandle } catch { break }
if ($hwnd -ne [System.IntPtr]::Zero) {
[HermesHandoff.Win32]::ShowWindow($hwnd, 9) | Out-Null # SW_RESTORE
[HermesHandoff.Win32]::SetForegroundWindow($hwnd) | Out-Null
Write-HandoffLog "focused relaunched desktop window"
break
}
Start-Sleep -Milliseconds 400
}
}
} catch {
Write-HandoffLog "WARNING: could not focus relaunched desktop: $($_.Exception.Message)"
}
break
}
Start-Sleep -Milliseconds 400
if ($script:Ui) { [System.Windows.Forms.Application]::DoEvents() }
}
if (-not $spawned) {
Write-HandoffLog "WARNING: explorer relaunch did not produce a $exeName process; falling back"
}
} catch {
Write-HandoffLog "WARNING: explorer relaunch failed: $($_.Exception.Message); falling back"
}
}
if (-not $spawned) {
try {
# Fallback keeps the old behavior (console tie-in and all) --