fix(m196): GUI 产物 PE Subsystem → WINDOWS_GUI(2),并用 AttachConsole 保住 CLI 输出
群友 2026-11-08 实测发布构建「运行时会带一个控制台窗口在底下」。根因:产物 PE 头 Subsystem 仍是 CUI(3)。同一个修复 2026-11-01 做过一次(37d3039),但只改了已被 workspace exclude 的 Slint 树(crates/app),从未到达 iced 产物。 - crates/app-iced/src/main.rs:加 #![cfg_attr(windows, windows_subsystem = "windows")], 并写清为什么放 bin 层而不是 build.rs(PE 子系统是每个 bin 目标的属性)。 - crates/app-iced/src/platform/win32/console.rs(新):AttachConsole(ATTACH_PARENT_PROCESS) 的落点 + 判据 should_attach(纯函数,可断言)。GUI 子系统进程不继承父控制台,实测 从 cmd 启动时三个 std 句柄全是 0;附着后 GetStdHandle 立刻给出控制台句柄(0x0→0x208), 所以不改 std 句柄、不碰用户的重定向(ATTACH_PARENT_PROCESS 只会附到已存在的控制台, 永不新建窗口)。 - packaging/check_pe_subsystem.py(新):读产物 PE 头 Subsystem 字段(GUI 必须 2、 CLI ull 必须 3),非 2 即红;--self-test 注入 5 条合成 PE 回归。 - 接进 release-build.yml(发布侧两槽位)与 ci.yml build job(PR 阶段)。 - guards.yml:unsafe 落点期望集合变成两处(console.rs + transparency.rs),集合相等判据其余不变; 平台层所有「全仓唯一 unsafe 落点」措辞同步改正。
This commit is contained in:
1 parent
30b61e2684
commit
14f9318e09
15 files changed
+693
-36
No files matched your search
@@ -65,6 +65,7 @@ Git Bash 下会静默落进 Docker VM(脚本内部用 `cygpath -m` 归一)
|
||||
| `packaging/release-notes.md` | GitHub Release 说明模板(`{{VERSION}}` / `{{SUMS}}` 占位) | ≤400 |
|
||||
| `packaging/check_screenshot.py` | 截图非空白判定(CI 门禁 + 本地手动跑,零第三方依赖) | ≤400 |
|
||||
| `packaging/check_publish_slots.py` | 发布名单守卫(M164):名单 ⇄ 产物两个方向;`--self-test` 注入 8 条回归 | ≤400 |
|
||||
| `packaging/check_pe_subsystem.py` | PE 子系统守卫(M196):**读产物 PE 头的 `Subsystem`**(GUI 必须 2 / CLI 必须 3),非 2 即红;`--self-test` 注入 5 条回归(见 §15) | ≤400 |
|
||||
| `packaging/check_test_source_off.py` | 测试通道守门(M169):workflow / 打包脚本 / `Cargo.toml default` 都不许打开 `update-test-source`;归属按 `jobs.*.steps[]` 列表项判、默认拒绝;`--self-test` 按 `tests/guard_vectors.json` 注入 | ≤400 |
|
||||
| `packaging/tests/guard_vectors.json` | 守门自测向量(基线 + 32 条:26 红 / 6 绿),数据与代码分开 | ≤400 |
|
||||
| `packaging/ci-runtime-smoke.md` | §11 的细节:断言口径/阈值依据/失效模式/复跑 | ≤400 |
|
||||
@@ -141,3 +142,26 @@ Git Bash 下会静默落进 Docker VM(脚本内部用 `cygpath -m` 归一)
|
||||
`ci.yml` 的 `update-e2e` job(**只在 Windows**:夹具的「真形状」是 Windows 裸 `.exe` +
|
||||
`portable-exe`;Linux/macOS 的真实产物是 `.tar.gz` + `portable-zip`,在本模块会被直接拒)。
|
||||
**不验**真 GitHub 下载、GUI 点击与重启替换(需人工)。
|
||||
|
||||
## 15. 产物 PE 子系统(M196:GUI 必须 `WINDOWS_GUI`=2)
|
||||
|
||||
群友 2026-11-08 实测发布构建「运行时会带一个控制台窗口在底下」。根因:产物 PE 头的 `Subsystem` 仍是
|
||||
CUI(3),`grep -rn windows_subsystem crates/` 当时零命中。同一个修复 2026-11-01 做过一次(`37d3039`),
|
||||
但只改了 `crates/app/src/main.rs`——那棵树自 M118 起被 workspace `exclude`、不进发布矩阵,所以那一笔
|
||||
**从未到达产物**。教训不是「忘了写属性」,而是没有一步去看产物本身。
|
||||
|
||||
- 修在哪:`crates/app-iced/src/main.rs` 顶上的 `#![cfg_attr(windows, windows_subsystem = "windows")]`。
|
||||
PE 子系统是**每个 bin 目标**的属性,`cfg_attr` 是它的原生长相;不放 `build.rs` 是因为那里要绕
|
||||
`cargo:rustc-link-arg` 间接改链接命令行,且会把「这条 bin 是 GUI」挪到看不见 `[[bin]]` 声明的地方。
|
||||
- 代价与补救:GUI 子系统进程**不继承**父进程控制台,stdout/stderr 在 cmd 里是 0 号无效句柄。所以
|
||||
`main()` 第一步调 `AttachConsole(ATTACH_PARENT_PROCESS)`(`crates/app-iced/src/platform/win32/console.rs`,
|
||||
四种启动情形的实测表在该文件顶部):重定向/管道两个句柄本来就可用(一个字节都不动)、cmd 里直接跑
|
||||
附着后输出落进控制台、双击时附着失败且**绝不新建窗口**。
|
||||
- 守门:`python3 packaging/check_pe_subsystem.py --gui <exe> --cli <exe>`,读 `MZ`→`e_lfanew`(`0x3C`)→
|
||||
`PE | ||||