修复登录自启的权限问题:低完整性目录、日志兜底与数据目录自检

登录任务本身没问题(InteractiveToken + HighestAvailable + --minimized),
ICACLS 也没有拒绝 ACE;真因是 exe 所在的 D:\dsh workspace 带 Low 强制标签,
Windows 用低完整性令牌运行这里的 exe,它写不了中完整性的 %LOCALAPPDATA%,
于是第一步写日志就 UnauthorizedAccessException,托盘起不来。

- FileLog 改为 fail-safe:首选目录失败依次回退 LocalLow / TEMP / ProgramData,
  缓存待写行,永不抛异常,暴露 ActiveDirectory 与 LastFailure;
- 启动自检增加数据目录可写性探测,致命对话框写出真实日志目录与低完整性判断;
- 新增 --logcheck 只读自检:输出程序路径、数据目录可写性、实际日志目录与结论;
- README 增加放置目录说明,validation.md 记录第八轮;
- 新增两条 FileLog 回归测试(本地 49/49,探测 16/16,Release 0 警告 0 错误)。
This commit is contained in:
chuzhongzai
2026-10-24 11:18:09 +08:00
parent 7be117057a
commit 545d96174d
6 changed files with 222 additions and 10 deletions
+23
View File
@@ -2,6 +2,29 @@
日期:2026-10-23(初版)、2026-10-24(第二轮修复)。环境:Windows 10/11 x64,开发机网卡 `以太网`(索引 16),IPv4 地址 `192.168.6.119/24`,主路由 `192.168.6.1`。
## 第八轮修复(2026-10-24,重启后登录自启报“Access to the path … is denied”)
症状:重启电脑后没有托盘图标,只弹一个对话框「程序无法继续:Access to the path 'C:\Users\emm\AppData\Local\GatewayKeepalive\logs\gateway-2026-10-24.log' is denied.」。
排查与真因:
- 计划任务本身没问题:`schtasks /Query /XML` 显示 `UserId=S-1-5-21-1629374972-835245509-3346384658-1001`、`LogonType=InteractiveToken`、`RunLevel=HighestAvailable`、动作 `GatewayKeepalive.exe --minimized`,触发器等登录用户。`schtasks /Run` 能复现同样的对话框。
- 权限表也没问题:日志目录、日志文件、以及 `C:\Users\emm\AppData\Local` 三层 `icacls` 全都有 `DESKTOP\emm:(F)`,没有被拒绝的 ACE;同样的脚本用同一个账号可以写。
- 真因在**所在目录的完整性级别**:`D:\dsh workspace` 被打了 Low 强制标签(`icacls` → `Mandatory Label\Low Mandatory Level:(OI)(CI)(NW)`),存在这里的 exe 会被 Windows 用**低完整性令牌**运行。低完整性进程写不了中完整性的 `%LOCALAPPDATA%`,于是第一步写日志就抛 `UnauthorizedAccessException`。把同一个 exe 复制到 `%LOCALAPPDATA%\Programs\GatewayKeepalive\` 再跑,`--logcheck` 立刻变成“数据目录 可写=True / 结论=写入成功”。
- 也就是说:这不是提权问题、不是任务配置问题、不是 ACL 问题,而是“程序放在哪运行”。修了两头——给出正确的放置位置,并让程序不再因为写不了日志而整个起不来。
修法:
- `FileLog` 改成 fail-safe:写入先进缓冲区,按「首选目录 → `%LOCALAPPDATA%Low` → `%TEMP%` → `%ProgramData%`」依次尝试,任何一步失败都不抛异常;`ActiveDirectory` / `LastFailure` 暴露真实落点与失败原因,切换目录时在日志里写一行“日志目录改为 …”。
- 启动时探测数据目录是否真的可写(建临时文件再删),自检行里带上「数据目录=… 可写=… 日志目录=…」;致命对话框不再只说一句错误,而是写出实际生效的日志目录与“程序可能放在低完整性目录里”的判断。
- 新增 `--logcheck`:只用当前身份验证“能不能写日志/数据目录”,不起托盘、不提权,输出「程序路径 / 数据目录 可写 / 首选目录 / 实际目录 / 结论」,方便用户自查。
本轮验证:
- 新增两条回归测试:首选目录可写时就用首选且不记失败;首选目录不可用(被同名文件占住)时不抛异常、回退到可用目录并把失败原因写进 `LastFailure`。本地测试总数 47 → 49,全绿;探测离线测试 16/16;Release 构建 0 警告 0 错误。
- 实测三种落点:`%LOCALAPPDATA%\Programs\GatewayKeepalive\GatewayKeepalive.exe --logcheck` → 可写=True、实际目录=`…\AppData\Local\GatewayKeepalive\logs`、写入成功;`artifacts\publish`(低完整性)下的同一 exe → 可写=False、实际目录=`…\AppData\LocalLow\GatewayKeepalive\logs`、写入成功(已回退),日志里确有该行。
- **未验证**:桌面托盘与登录任务仍需把 exe 换到用户目录后由用户重启确认一次(本机命令行没有提权能力,不能改计划任务的动作路径)。
## 第七轮修复(2026-10-24,关闭登录自启必报错:按 HRESULT 而不是按异常类型判断)
症状:点「登录后自动启动」必弹「开机自启设置失败:找不到文件或目录:系统找不到指定的文件。(0x80070002) 已回滚到原设置。」,这个开关因此永远关不掉。