对话档案 D08 · 静默启动与黑窗口排障(11-10)
一句话:两条消息、193 万 token,把一个「越藏越糟」的问题翻了过来——
-WindowStyle Hidden从来不是隐藏,而是先建窗口再藏起来;真正的解法是让进程根本不在桌面上出生,再给它一个能被人看见的入口。
一、这段对话怎么走的
| 阶段 | 用户要求 | 产出 | 卡点 |
|---|---|---|---|
| 现象陈述 | 后台任务静默启动后,不知道它什么时候会启动;依然会打断操作;怀疑是「启动后把黑窗口隐藏」 | 定位到计划任务的登录类型是 Interactive,-WindowStyle Hidden 只是建窗后隐藏 | 用户对实现方式的猜测是对的,但需要证据才能定案 |
| 根因确认 | 「帮我检查一下这些问题」 | 核对任务 XML 的 LogonType、launch.ps1 的启动方式、.bat 与 .ps1 的差别 | 改成 S4U(session 0)需要管理员权限,set-s4u.ps1 备好但必须用户手动提权运行 |
| 第二条诉求 | 「能不能这样:用 Python 写一个小应用程序……最好还有一个右下角任务栏的小图标」 | ops/kaoyan-panel.py(约 23KB,tkinter + pystray 托盘)、panel.bat、panel-admin.bat | 内置 Python 没有 pystray / Pillow,必须用官方 Python 3.13 解释器 |
| 收尾 | 能开、能关、能干净退出 | 五个计划任务的启停/重启、HTTP 体检、自愈巡检一键开关、当前隧道域名、最近一次巡检结果、管理员切换 S4U | S4U 生效后桌面 toast 会失效,可观测性转由 selfheal.log / outbox/ / 面板承担 |
这次对话只有 22 分钟。短,但信息密度很高——它是整个两个月里,唯一一次「用户提出的方案比 AI 的更对」的案例。
二、用户的关键原话
原话一(问题陈述,几乎自带诊断)
「我之前让 workbuddy 做一个后台代码任务,和重启服务器有关,然后觉得他会是不是弹出黑窗口影响我操作,所以我让他设置静默启动。但是现在的问题是,静默启动后,我完全不知道他什么时候会启动,他好像是用启动后把黑窗口隐藏的方式实现的,但是依然会打断我的操作,我还不知道该怎么办。帮我检查一下这些问题。」
点评:这条消息做了三件很难得的事。第一,把历史决策链交代清楚了(当初为什么要静默);第二,给出了自己的因果假设(是「先建窗再隐藏」);第三,明确了当前困境(不是窗口难看,而是「不知道什么时候会启动」)。缺点是「打断我的操作」这个现象没有给频次和时刻——是每 30 分钟一次,还是每次登录一次?这一点只能靠日志反推。
原话二(把可观测性缺陷转化成产品需求)
「能不能这样:我想让你用 python 写一个小应用程序,这样我可以方便的操控他,让他开启或退出,或者用管理员模式打开。然后在这个应用程序中自动完成这些后台任务重启和检测的工作,让信息和服务器都被限制在这个应用程序中,我可以选择开启或关闭。最好还有一个右下角任务栏的小图标提示,可以干净的退出这个程序。」
点评:这是全篇最有价值的一句。用户没有继续要求「再藏得深一点」,而是反过来说:既然看不见,就给我一个看得见的地方。他还顺手把验收条件写全了——托盘图标、可开关、可管理员模式、能干净退出(不是杀进程)。这四条正好覆盖了后台程序最容易被做残的四个点。
三、成本与效率
| 指标 | 数值 | 折算 |
|---|---|---|
| 总 token | 1,939,025 | 输入 1,910,920 / 输出 28,105,输入:输出 ≈ 68:1 |
| 用户消息 | 2 条 | 单条均 969,513,约 97 万 |
| 工具调用 | 36 次 | 单条消息均 18 次;API 请求 33 次 |
| 时长 | 约 22 分钟 | 14:51 至 15:13 |
| 单次产出 | kaoyan-panel.py 约 23KB | 约 8.4 万 token / 千字节代码 |
97 万 token 换一条消息,听起来很贵,但折算到产出就不难接受:一个能替代「每 30 分钟闪一次黑窗」的托盘程序,此后每天省掉的注意力远大于这 193 万。这一篇是整个系列里性价比最高的一次会话——因为它的产物是减成本的基础设施,而不是又一层自动化。
对比 D06 的 39 万 token / 次巡检,这次会话贵 2.5 倍,但它的产出被复用了几十次。真正该问的不是「这条消息花了多少」,而是「这个产物会被调用多少次」。
四、曲折点与评判
1. 根因判断准确:-WindowStyle Hidden 是建窗后隐藏(★★★★)
这一条值得单独记。.bat 在交互式计划任务里必然弹出控制台,因为 cmd.exe 需要一个真实控制台;-WindowStyle Hidden 只影响窗口显示属性,不改变进程是否拥有控制台。所以「静默」从来没有实现过,只是把窗口的存在时间压到了几十毫秒——用户看到的那一闪,就是它。诊断这一步没有走弯路,是这次会话短的根本原因。
2. 第一解法卡在权限上,第二解法来自用户(★★★★★)
彻底解法是 S4U:让任务在 session 0 运行,物理上不在用户桌面创建任何窗口。代价是需要管理员提权注册任务,set-s4u.ps1 写好了但只能等用户手动跑;而且 S4U 之后桌面 toast 失效,通知链路要重做。
就在这个卡点上,用户提出了托盘面板。这个方案的妙处在于它同时解决了两个问题:S4U 解决「不出现」,面板解决「看得见」。如果只做 S4U,问题会从「黑窗干扰」变成「彻底失联」——这正是用户原话里已经点出的困境。
3. 静默与可观测性被当成同一件事(★★)
前一轮的决策逻辑是「干扰 -> 隐藏」,把可观测性当成了干扰的来源。实际两者是独立的:窗口可以不要,状态必须在。这个认知偏差持续了大约三周(从 10 月中后台任务建立到 11-10),期间用户一直处在我不知道它在不在跑的状态。
五、提示词与流程改进
改进一:说「不要窗口」,不要说「静默」
反例:
设置静默启动,不要弹黑窗口
正例:
让进程在 session 0 运行(S4U),桌面上不创建任何窗口。接受 toast 失效,状态改由
selfheal.log和托盘面板呈现。验收:任务 XML 里LogonType是S4U,运行中进程的SessionId为 0。
「静默」这个词在 Windows 上有歧义,它既可以是「窗口不可见」,也可以是「不创建窗口」,前者的实现遍地都是坑。
改进二:现象要给频次和时刻
反例:
还是会打断我的操作
正例:
每 30 分钟一次,整点后约 10 秒闪一下,持续不到半秒;登录时也会闪一次。这两个时刻正好对应两条触发器。
有了频次与触发器时刻的对应关系,根因几乎不用推。
改进三:先要可观测,再谈彻底
反例:直接上 S4U,把最后的可见性也一起关掉。
正例:
第一步先加一个能看状态的入口(日志或托盘),确认状态可信;第二步再消除窗口。两步之间要能互相验证。
六、可复用结论
-WindowStyle Hidden不是隐藏,是「先建窗后隐藏」;要真正无窗,只能让进程不在交互会话里出生(S4U / session 0)。- 消除干扰和消除可观测性是两件事,任何「让它安静点」的需求,都要同时给一个替代的观察入口。
- 当修复卡在权限这类硬约束上时,换一个能满足同一目标的形态(托盘面板),比继续攻权限更划算——这次是用户先想到的。