fix: 原生窗口销毁后宿主事件循环未退出

This commit is contained in:
Codex
2026-10-05 00:51:43 +08:00
parent 568ffc40eb
commit c0eca1d4bd
5 changed files with 125 additions and 7 deletions
+43
View File
@@ -105,6 +105,44 @@ function Wait-Window([Diagnostics.Process]$process, [string]$title, [int]$timeou
throw "Window not found: $title"
}
function Assert-NativeCloseExitsProcess([string]$fixturePath, [string]$runDir, [string]$scenario) {
# 模拟标题栏关闭命令。EasyX 的窗口过程位于内部线程,宿主 peekmessage 不保证能看到 WM_CLOSE;
# 无论关闭消息是否进入 EX_WINDOW,原生 HWND 销毁后 fixture 都必须自行结束。
New-Item -ItemType Directory -Force -Path $runDir | Out-Null
# EasyX 在重定向标准输出的子进程中可能返回 0xC000013A;关闭回归不需要捕获输出,
# 因而保持与用户直接运行应用相同的控制台继承方式。
$process = Start-Process -FilePath $fixturePath -ArgumentList @($scenario, $runDir) -PassThru
try {
$h = Wait-Window $process "StellarX.UI.$scenario"
if ($scenario -eq 'modal-close') {
# fixture 在首次绘制后立即进入 showModal;给模态循环一个有界启动窗口。
Start-Sleep -Milliseconds 250
}
if (-not [StellarXUiNative]::PostMessage($h, 0x0112, [IntPtr]0xF060, [IntPtr]::Zero)) {
throw 'Failed to post SC_CLOSE to fixture'
}
if (-not $process.WaitForExit(5000)) {
$process.Kill()
$process.WaitForExit()
throw 'Fixture process remained alive after native window destruction'
}
# EasyX 的 EX_SHOWCONSOLE fixture 由 Start-Process 托管时,原生标题栏关闭在部分
# 控制台宿主中会映射为 STATUS_CONTROL_C_EXIT;它与“进程未退出”是不同问题。
if ($process.ExitCode -notin @(0, -1073741510)) {
throw "Fixture close regression exited with code $($process.ExitCode)"
}
@{ nativeCloseExited = $true; scenario = $scenario; exitCode = $process.ExitCode } |
ConvertTo-Json -Compress | Set-Content -Encoding UTF8 (Join-Path $runDir 'close-result.json')
}
finally {
if (-not $process.HasExited) {
$process.Kill()
$process.WaitForExit()
}
$process.Dispose()
}
}
function Client-Point([IntPtr]$h, [int]$x, [int]$y) {
# 将 fixture 客户区坐标转换为 SendInput 所需的全局屏幕坐标。
return [StellarXUiNative]::GetClientPoint($h, $x, $y)
@@ -298,6 +336,11 @@ try {
$process.Dispose()
}
}
Assert-NativeCloseExitsProcess $fixture `
(Join-Path $sessionRoot "run-$iteration-native-close") 'native-close'
Assert-NativeCloseExitsProcess $fixture `
(Join-Path $sessionRoot "run-$iteration-modal-native-close") 'modal-close'
}
}
finally {