Argus
文档目录 · v0.3.4 文档首页

使用指南

界面与操作硬件数据的来源与限制常驻、托盘与快捷键设置

开发指南

环境与命令构建与缓存多语言性能基线与测量提交与发布依赖与安全维护Windows 代码签名

架构

架构管理员启动采集层 argus-core前端Tauri 宿主特权服务系统任务管理器替换技术栈

设计

设计原则曲线动画全局快捷键窗口外观

项目

已知问题路线图
搜索文档

系统任务管理器替换

Argus 提供默认关闭的系统任务管理器替换。界面入口在“设置 → 权限”,只在发布版且特权服务授权给当前账户时允许开启。开启需要管理员授权;关闭优先使用特权服务,服务不可用时使用管理员维护助手。

启动路径

固定修改 HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Image File Execution Options\taskmgr.exe 的 Debugger 值,类型为 REG_SZ,内容是带引号的独立启动器绝对路径及 --task-manager。不修改其他值、键权限或系统可执行文件;发现已有 Debugger(包括空值)、UseFilter 或子项时拒绝启用。此时状态说明写明发现的是哪一项(Debugger 的值、UseFilter、前几个子项的名称及总数),诊断日志只记类别(Debugger 指向 Argus 的启动器、其他程序、为空或不是文本,UseFilter,子项数量及其中是否有 PerfOptions),不记值。

IFEO 会把调试器前缀加入原启动命令,因此按程序名影响整台电脑,不局限于 Ctrl+Shift+Esc,也不能靠普通启动一次 taskmgr.exe 绕过。参见 Microsoft 的 IFEO 命令行说明。Windows 11 上该注册表分支在 WOW64 视图之间共享,不另写 Wow6432Node,见 WOW64 注册表规则。

启动器与独立恢复程序从 Argus 发布程序内嵌的字节安装到受保护的 Argus Privileged 目录,不从相邻的可写 sidecar 加载。界面也复制为该目录中的独立版本文件,移动原免安装版不会留下悬空的 IFEO 路径。副本在 IFEO 自检通过后才复制,启用失败时删除本次的副本;每次启用、恢复、更新或卸载特权服务,以及安装程序更新替换时,删除未完成的恢复记录没有引用的旧副本,仍在运行的跳过,下次再删。以副本运行的 Argus 开启“登录 Windows 时启动”时,启动项写入已安装的 argus.exe,不写会被删除、也不随更新替换的副本;已安装的 Argus 读取设置时,或再次启动、转交给已在运行的实例后,把旧版本的副本写下的启动项改回自身:后者覆盖登录时由启动项打开的旧副本正占着单实例的情况,此时新版本走不到读取设置这一步。目录与文件沿用特权服务的管理员和 SYSTEM 写入权限校验。

启动器只为授权账户尝试启动 Argus;其他账户直接尝试原生任务管理器。启动入口先在调用者会话中以标准权限运行;已开启管理员运行时,入口在创建单实例和 WebView 之前转交同账户、同会话的管理员任务。未开启时沿用普通权限:未提升的启动器直接创建界面;提升后的启动器(例如从管理员身份的命令提示符运行 taskmgr)把界面创建为桌面外壳(资源管理器)的子进程(PROC_THREAD_ATTRIBUTE_PARENT_PROCESS),界面继承外壳的标准令牌;找不到外壳或外壳不属于同一账户时回到原生路径。账户没有拆分令牌(关闭 UAC、内置 Administrator 账户)时只有一种令牌,界面与平时一样以它运行。界面的环境变量按当前账户重新生成,不沿用创建者的环境。

不使用提升令牌的关联令牌(TokenLinkedToken):没有 SeTcbPrivilege 的进程取到的只是识别级令牌,Windows 拒绝据此创建主令牌(ERROR_BAD_IMPERSONATION_LEVEL,在普通权限下对受限令牌的关联令牌实测);没有拆分令牌的账户则没有关联令牌可取。

开启时的界面自检按发起者 PID、创建时间、账户及会话核对后,把自检进程创建为发起者进程的子进程,继承发起者的令牌,因此 UAC 使用另一管理员凭据也不会把界面开到管理员账户下。这种情况下发起者进程的 DACL 不授予管理员账户任何权限,维护助手启用 SeDebugPrivilege 后再打开它;令牌只需读取用户,管理员组对令牌有查询权限。服务不启动 SYSTEM 权限的交互界面。

界面唤起有独立的就绪握手,进程创建成功不算完成。前端挂载后或收到唤起事件时确认,启动器等待 10 秒,再给显示确认 2 秒。握手使用随机名称、账户 ACL、父进程创建时间及固定启动器路径;父进程退出后,迟到的请求不显示窗口。单实例仍显示已有窗口,不切换为隐藏;超时也不结束已有 Argus。专为此次请求创建、始终未显示的界面实例在 15 秒后退出。

单实例交接支持标准权限进程连接已运行的管理员实例:互斥锁仅申请 SYNCHRONIZE,专用消息窗口仅允许 WM_COPYDATA 穿过 UIPI;参数长度、格式和握手身份仍需校验。交接进程以 0 退出后继续等待原窗口确认,非零退出立即报告退出码;交接失败的握手进程记录原因并退出,不另弹出阻塞自检的对话框。

开启与恢复记录

  1. 锁定专用安装目录,检查授权账户和现有 IFEO 配置。
  2. 删除不再使用的界面副本,准备启动器和恢复程序。
  3. 在管理员维护助手中创建随机名称的无窗口启动器副本,分别检查普通启动,以及带调试标志创建、脱离并恢复运行后的正常退出。自检不创建或写入临时 IFEO 条目;对随机程序的重定向许可不能代表对 taskmgr.exe 的修改许可。清理完成后复制界面副本和 taskmgr-recovery.txt 应急说明,再以发起者标准权限完成界面就绪检查。任何启动或清理失败均不写入 taskmgr.exe 的 Debugger。自检失败与清理失败分别报告,保留原始错误。
  4. 将 taskmgr-recovery.json 的 Prepared 记录写入受保护的新文件、同步并替换;记录原值的存在性、类型与原始字节、本次写入值、账户和界面副本名。第一版拒绝接管已有 Debugger,因此有效原值为不存在。
  5. 再读一次当前状态,写入 Debugger、刷新注册表并读回核验,最后将记录改为 Active。

恢复先检查当前值仍与本次写入值完全一致,再记录 Restoring、恢复原值、刷新并核验,最后记录 Restored。实际状态已经是原状态时,恢复是幂等的;第三方修改或不可信备份会中止自动恢复并保留文件。只删除 Debugger 值,不删除整个 taskmgr.exe 键;新建后留下空键不影响 Windows 启动行为。

注册表值与记录文件不是跨资源原子事务。断电发生在任意阶段时,Prepared / Restoring 记录使下次服务启动或恢复操作可以继续还原;恢复记录损坏时须人工核对。安装锁只串行化 Argus 自己的操作,无法锁住同时修改注册表的第三方管理员工具,所以每次写入前后都重新核验,检测到冲突便停止。

启动自检先将测试程序名写入独立记录 taskmgr-probe.txt;恢复、下次自检或服务启动时会清理中断留下的临时文件。旧版本可能还留有对应的 IFEO 条目:仅在名称与记录一致、Debugger 仍是旧版自检值且没有过滤配置时清理;被其他程序改动的条目保留并报错。新自检只创建文件,旧条目不存在时不发起注册表删除操作。taskmgr.exe 的替换值不因自检而临时增删。

注册表访问按操作申请权限:读取状态只需查询值与枚举子项,写入只需设置值与刷新键所需的查询权限,不申请通知等无关权限。自检条目或 taskmgr.exe 条目的调用以 ERROR_ACCESS_DENIED 被拒时,维护助手用 AccessCheck 只读地核对当前令牌及该调用实际所需的权限;仅创建尚不存在的条目时,检查 IFEO 父键的创建子项权限。DACL 检查通过不能说明拒绝一定来自防护软件:句柄权限、令牌限制、完整性级别、系统策略及注册表过滤都可能影响调用,需结合具体失败的 API、错误码及相关记录判断;检查未通过只说明 DACL 未授予所检查的访问权限,不推断权限曾被谁修改。Argus 不修改注册表权限或绕过访问限制。

原生回退与应急恢复

原生路径使用系统目录的固定 taskmgr.exe,不执行 IFEO 附带的任意路径或把附带参数转发给 Argus。先以 DEBUG_ONLY_THIS_PROCESS | CREATE_SUSPENDED 创建,再设置退出时不结束被调试进程、脱离调试并恢复线程,避免再次进入 IFEO。脱离失败会清理本次新建的进程并报错,不结束其他进程。API 行为见 DebugActiveProcessStop 和 DebugSetProcessKillOnExit。

此路径不依赖服务、Tauri 或 WebView2。系统策略、令牌限制或文件损坏仍可能使原生启动失败,启动器会提示错误;不能保证已损坏或被删除的启动器自行恢复。

独立恢复程序为受保护目录中的 argus-taskmgr-recover.exe,直接运行会请求管理员权限,不要求 Argus 界面或服务可用。如果它也损坏,可从 Win+R 打开管理员注册表编辑器,核对 Debugger 确实指向此安装的启动器,且可信恢复记录的原值不存在,再只删除该 Debugger 值。已有第三方值不得删除;备份缺失时先人工确认归属。

更新和卸载

卸载特权服务前必须先完成恢复。更新特权服务时,替换处于启用状态(记录为 Active,Debugger 仍是 Argus 写入的值且没有过滤)则先让替换跟上新版本,再更新服务,替换保持开启:启动器自行创建界面,不经过服务,替换所用的文件也与服务的程序文件分开,更新服务时不必关闭替换。整个过程不改动 IFEO 的值,也不重新自检,因此不会在无人确认时改动系统入口。其他状态(启用或恢复尚未完成、Debugger 已被改写)与卸载一样先完成恢复,冲突、记录损坏或写入失败会阻止继续。恢复记录已是 Restored 时,Argus 写入的值已经还原,此后 taskmgr.exe 键中的 Debugger、UseFilter 或子项属于其他程序,保持原样,也不阻止服务更新或卸载;记录尚未完成恢复而键中出现其他程序的配置时仍会阻止,提示写明是其他程序的配置,需在写入它的工具中关闭。

安装程序更新 Argus 时,先由新安装的 argus.exe --argus-close-copies 结束正在运行的任务管理器替换界面副本,再以同样的方式更新服务(安装后钩子,见特权服务)。即使服务已卸载,也会关闭这些副本,避免升级后的启动被转交给旧版本。让替换跟上新版本的步骤:先把发起更新的 argus.exe(安装程序更新时为新安装的程序)复制为新名称的界面副本,再原地替换启动器和恢复程序,然后把恢复记录改为指向新副本,最后更新应急说明并删除旧副本。IFEO 的值只指向启动器,保持不变,因此不改动系统入口,也不重新自检。界面副本正在运行时既不能替换也不能删除,所以新版本使用新名称,旧副本退出后在下次清理时删除;启动器正在运行时替换失败,本次的新副本随之删除,记录和原来的副本保持不变,服务也不更新,提示稍后重试或先恢复再更新。这一步不重新做界面就绪检查;新版界面未能就绪时,启动器照常改为打开 Windows 任务管理器,并把原因写入 taskmgr.log。替换已关闭、尚未完成或已被其他程序改写时这一步不做改动,按上一段处理。

免安装版直接替换程序文件时不经过安装程序;安装程序更新服务失败时只返回非零退出码,钩子不提示。这两种情况下替换继续打开旧版本的副本,直到在设置中更新服务。状态读取时比较记录所指副本的文件版本与当前版本(只比较主、次、修订号),副本较旧时状态仍为已启用,说明中写明副本的版本号,提示更新服务;诊断日志只记版本号。仅手动更新服务不会结束正在运行的界面副本;旧副本仍占着单实例时,之后的启动会转交给它,直到它退出。

NSIS 的卸载前钩子(src-tauri/installer-hooks.nsh)先以 argus.exe --argus-close-copies 结束正在运行的界面副本(卸载程序的 Restart Manager 只认识安装目录中的 argus.exe;留下的副本占着单实例,重新安装后的首次启动会转交给它,也删不掉),再询问是否一并卸载特权服务(卸载服务时同样先恢复),再做恢复检查:优先调用独立恢复程序,缺少该程序时调用 Argus 的早期维护模式;取消授权或恢复失败会停止卸载。升级安装时选择“先卸载再安装”,安装程序会就地运行旧的卸载程序($EXEDIR 等于 $INSTDIR),而真正的卸载从 %TEMP% 中的副本运行;钩子据此跳过就地卸载的这两步,因为替换所用的文件都在服务目录,不随 GUI 删除。恢复程序及备份会保留在服务目录,避免在恢复过程异常时失去最后的修复入口;恢复、更新或卸载服务时只删除不再使用的界面副本,仍在运行的不会被强行删除。

代码与验证

crates/argus-service/src/taskmgr/ 按职责分为状态机、固定注册表适配、启动自检、启动与令牌处理、前端握手;两个 src/bin/argus-taskmgr-*.rs 生成独立程序。Tauri 发布构建先构建这两个程序,再把字节内嵌进 Argus。开发版不会提供启用功能。

服务协议第 4 版只新增无参数的 RestoreTaskManager,没有通用写注册表、任意命令或路径接口。开启仍走明确授权的管理员维护助手。恢复失败时允许独立助手重新核验后重试,这个恢复动作按记录幂等。

普通测试使用内存注册表和自己创建的子进程,覆盖备份失败、提交失败回退、中断阶段恢复、重复恢复、第三方冲突、过滤键拒绝、恢复失败保留记录、恢复后出现的第三方值不阻止服务维护、更新服务时哪些状态让替换跟上新版本、保持开启,更新替换文件的顺序与失败回退、命令行转义、真实调试创建后的脱离和运行结束,以及指定父进程时的令牌继承(低完整性父进程下创建的子进程同为低完整性,而不是创建者的中完整性)。启动自检覆盖普通启动与调试启动失败、无注册表写权限时仍能检查启动器、临时文件清理、旧版 IFEO 条目清理和第三方配置保留;发布启动器另在普通权限下验证两种启动方式。注册表项权限的判断在 HKCU 下的临时键上验证,测完删除。它们不写入真实 IFEO,也不运行系统任务管理器。

维护助手出错时,把出错的步骤、提示文字、错误分类和注册表调用信息写入服务目录中的 taskmgr-error.json。发起操作的界面读回后在设置页显示提示文字;诊断日志只记固定的步骤名、错误分类、API 名、访问掩码、Windows 错误码及 DACL 检查结果,不记提示文字或路径。自检与清理同时失败时,分别保留两次失败的调用和权限检查结果,避免清理错误覆盖原始错误。助手每次运行前清掉上一次的记录(包括 0.1.0 的 taskmgr-error.txt),写不进去时才弹出消息框。启动器没有窗口:没能打开 Argus、改为打开 Windows 任务管理器时,或者开启时的界面自检失败时,它把原因追加到当前账户日志文件夹中的 taskmgr.log(超过 256 KB 时重新开始)。

taskmgr.log 同时记录早期单实例交接的失败 API、HRESULT、双方完整性级别及耗时,以及界面握手的具体阶段、启动器权限、子进程是否仍运行和退出码。接收方验证父进程、启动器映像或事件失败时记录对应检查;不记录进程路径、账户名或启动参数。

在 GitHub 查看此页