Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 11 additions & 5 deletions bin/stop-emrg.cmd
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,9 @@ REM stuck at "停止已有进程" because the windowless pythonw daemon holds fi
REM and Inno CloseApplications cannot see it).
REM
REM Order matters (mirrors bin/emrg-uninstall steps 1a/1b):
REM 1. GUI (EMRG.exe): graceful WM_CLOSE first (taskkill without /F),
REM /F fallback after ~5s if still alive
REM 1. GUI (EMRG.exe): graceful WM_CLOSE first (taskkill without /F), then
REM UNCONDITIONAL /F after the ~5s grace window (host 01:27:07Z: long-lived
REM GUI deferred WM_CLOSE past 5s — /F must not be gated on a survivor check)
REM 2. TUI (python.exe -m emrg): command-line filter (wmic, PowerShell
REM fallback), excludes the daemon (pythonw.exe -m emrg.server)
REM 3. daemon: `emrg server stop` protocol shutdown via the OLD install's CLI
Expand All @@ -20,14 +21,19 @@ setlocal enabledelayedexpansion
set "EMRG_DIR=%USERPROFILE%\.emrg"
set "INSTALL=%EMRG_DIR%\install"

REM --- 1. GUI: graceful WM_CLOSE, then /F fallback ---
REM --- 1. GUI: graceful WM_CLOSE, then unconditional /F after the grace window ---
REM (host report 2026-08-10T01:27:07Z: a long-lived ~15h GUI session deferred
REM WM_CLOSE past the 5s window — two full script runs did not terminate it
REM while a direct `taskkill /IM EMRG.exe` did. => the /F fallback must be
REM UNCONDITIONAL after the wait so an old GUI session can never hold the
REM installer hostage. When the GUI is not running, the graceful taskkill
REM returns errorlevel 1 (skip the wait) and the /F below is a fast no-op.)
taskkill /IM EMRG.exe >nul 2>&1
if not errorlevel 1 (
REM give the GUI up to ~5s to exit cleanly (ping = portable sleep)
ping -n 6 127.0.0.1 >nul 2>&1
)
tasklist /FI "IMAGENAME eq EMRG.exe" 2>nul | findstr /i "EMRG.exe" >nul
if not errorlevel 1 taskkill /F /IM EMRG.exe >nul 2>&1
taskkill /F /IM EMRG.exe >nul 2>&1

REM --- 2. TUI: python.exe -m emrg (daemon is pythonw.exe -m emrg.server, excluded) ---
where wmic >nul 2>&1
Expand Down
8 changes: 8 additions & 0 deletions tests/test_installer_stop.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,14 @@ def test_stop_emrg_cmd_covers_gui_tui_daemon_in_order():
assert "taskkill /IM EMRG.exe" in content
assert "taskkill /F /IM EMRG.exe" in content
assert content.index("taskkill /IM EMRG.exe") < content.index("taskkill /F /IM EMRG.exe")
# 宿主 2026-08-10T01:27:07Z 实测:长活 ~15h GUI 会话 WM_CLOSE 在 5s 窗内未退出,
# 两次整跑未终止、直接 taskkill /F 才终止 → /F 必须是无条件兜底(不 gate 在
# survivor 检查上),否则旧 GUI 会话可无限期拖住安装器。判别:ping 等待之后、
# /F 之前不得再有 findstr 判定。
ping_idx = content.index("ping -n 6 127.0.0.1")
f_idx = content.index("taskkill /F /IM EMRG.exe")
assert ping_idx < f_idx
assert "findstr" not in content[ping_idx:f_idx]
# TUI:命令行过滤(wmic LIKE 通配符须 %% 转义)
assert "wmic" in content and "commandline like" in content
assert "powershell" in content # wmic 缺失(Win11 24H2+)时的回退
Expand Down
Loading