根因:start_gmweb() 用 sys.executable 拉起 gmweb/serve.py,源码运行时是 python.exe,PyInstaller 单文件打包后却是启动器自身 —— 于是 `exe serve.py` 又开了一个启动器,新启动器再去拉 serve.py,每代顺延一个端口并各开一个 空窗口,直到 19546 端口用尽。开发机因为 18112 早被占用走了 early return, 所以看不出来。 - 新增多调用模式 run_script_instead():exe <xxx.py> [args] 时用 runpy 直接 执行该脚本,不开窗口/不提权/不占互斥量,打包后拉起 serve.py 才合法 - 新增单实例互斥(Local\DNF90Launcher-5E9C1B7A):重复启动把已有窗口 ShowWindow+SetForegroundWindow 后退出,不再开第二个窗口 - start_gmweb() 增加就绪校验:spawn 后最多等 6 秒确认 18112 在监听,未监听 则改用 importlib 在本进程线程里跑 serve.py 的 main(),绝不再拉起新窗口 - self_elevate() 提权重启带上原始参数(原来 ShellExecuteW 传 None,参数全丢); DNF90_GMWEB_CHILD=1 的子进程不再触发 UAC - WebView2 数据目录固定到 %LOCALAPPDATA%\DNF90Launcher\WebView2 且 private_mode=False,避免 exe 在只读目录/网络盘时窗口空白且无报错; 启动前查注册表确认运行时是否存在 - 新增 启动器日志.txt(exe 同目录,512KB 转 .old.txt):console=False 下 print 与未捕获异常全部落盘,顶部记录 pid/argv/SERVER_ROOT - 文档:新增 docs/启动器窗口风暴排查.md(现象、根因、复现手法、修复点、 日志判读表),README 常见坑与文档索引、docs/README、launcher/README 同步
42 lines
2.0 KiB
Markdown
42 lines
2.0 KiB
Markdown
# 整合启动器 + GM 管理工具
|
||
|
||
单 EXE 的 DNF90 启动器,内置完整 GM 管理工具(角色管理、道具发放、邮件、背包装备、拍卖行、任务、副本、钱包点券、删档等)。
|
||
|
||
## 技术栈
|
||
|
||
- **Python 3.15**(32 位)+ **pywebview 6.x**(Edge WebView2 内嵌窗口)
|
||
- 纯标准库 HTTP 后端 + 原生 HTML/CSS/JS 前端
|
||
- **PyInstaller** 打包单文件 EXE
|
||
|
||
## 文件说明
|
||
|
||
| 文件 | 说明 |
|
||
|------|------|
|
||
| `server.py` | 整合后端(启动器 + GM 工具,纯标准库) |
|
||
| `db.py` | SQLite 数据访问层(删角色/删档/疲劳/物品名缓存) |
|
||
| `native.py` | Native API 客户端(完整 GM 端点) |
|
||
| `index.html` / `style.css` / `app.js` | 双视图前端 |
|
||
| `DNF90启动器.spec` | PyInstaller 打包配置 |
|
||
| `sponsor.png` / `sponsor_qr.png` | 赞助二维码 |
|
||
| `qr/` | 关于页二维码(alipay / wechat / gzh / qq,可被 exe 同目录的同名文件覆盖) |
|
||
| `启动器日志.txt` | 运行日志(运行时生成,exe 同目录,超过 512KB 转 `.old.txt`) |
|
||
|
||
## 运行时约定
|
||
|
||
- **单实例**:命名互斥量 `Local\DNF90Launcher-5E9C1B7A`,重复启动只会把已有窗口提到前台
|
||
- **多调用模式**:`DNF90启动器.exe <xxx.py> [args]` 会用 `runpy` 直接执行该脚本。打包后 `sys.executable` 就是 exe 自己,`start_gmweb()` 正是靠这条路径拉起 `gmweb/serve.py` 的
|
||
- **提权**:UAC 自提权重启会带上原始参数;`DNF90_GMWEB_CHILD=1` 的子进程不再提权
|
||
- **WebView2 数据目录**:固定在 `%LOCALAPPDATA%\DNF90Launcher\WebView2`,避免 exe 在只读目录/网络盘时窗口空白
|
||
- 排障与现场取证见 [`docs/启动器窗口风暴排查.md`](../docs/启动器窗口风暴排查.md)
|
||
|
||
## 打包
|
||
|
||
```bash
|
||
cd launcher
|
||
python -m pip install pywebview pythonnet clr-loader pyinstaller
|
||
python -m PyInstaller --clean --noconfirm "DNF90启动器.spec"
|
||
# 产物:dist/DNF90启动器.exe
|
||
```
|
||
|
||
> 详见 [`docs/开发文档.md`](../docs/开发文档.md) 完整说明(环境搭建、架构、API 契约、常见问题)。
|