一开始只是 Claude 更新完打不开,想重装一下。结果三个小时没出门。
起点很朴素:双击 Claude Setup.exe,bootstrapper 报错 0x80073CF6 ERROR_INSTALL_PACKAGE_ALREADY_EXISTS,说包已经存在装不上。但 Get-AppxPackage *Claude* 返回空,系统层面看不到任何 Claude 包。这两件事同时为真,就说明有东西处于”已注册到内核,但用户态 API 看不到”的状态。
第一层:找锁文件的人
部署日志里全是 0x20:
删除文件 \\?\C:\Users\<user>\AppData\Local\Packages\Claude_pzs8sxrjxfjjc\SystemAppData\Helium\User.dat 时出错。错误代码: 0x20。0x20 是 ERROR_SHARING_VIOLATION。Helium\User.dat 是 MSIX 包的私有注册表 hive —— 每个 MSIX 应用运行时,Windows 会把这个文件挂载成一份独立的 hive,应用写注册表实际写到这里,跟系统注册表隔离。好设计,但这也意味着只要文件被某个进程打开,整个卸载/更新流程就走不下去。
handle64.exe 扫了一遍,直接定位到嫌疑人:
chrome-native-host PID: 28516C:\Users\<user>\AppData\Local\Packages\Claude_pzs8sxrjxfjjc\LocalCache\Roaming\Claude\Chrom...这是 Claude for Chrome 扩展的 native messaging host。Chrome 只要扩展在跑,就会持续把这个 host 拉起来。Claude 主进程退了,host 还活着。
Stop-Process -Id 28516 -Force 干掉它,但问题没完 —— 只要 Chrome 里 Claude 扩展还启用着,浏览器下一次需要通信时会把 host 重新拉起来。真要干净得把浏览器也关了。
第二层:内核里的僵尸 silo
干掉 native host 后我以为能继续了,结果 Remove-Item 依然报 正由另一进程使用。handle.exe 这次什么都找不到:
No matching handles found.用户态进程没人持有,但系统说被占。这指向一个更深的层级 —— kernel。查一下 hive list:
reg query "HKLM\SYSTEM\CurrentControlSet\Control\hivelist" | Select-String "pzs8sxrjxfjjc"出来一堆 \REGISTRY\WC\Silo4f96b625-... 开头的条目,全指向 Claude 包里的 User.dat、UserClasses.dat、Cache\*.dat。
\REGISTRY\WC\ 是 Windows Container registry silo 命名空间。每个 MSIX 应用运行时都有一个 silo,做注册表隔离。问题是 Claude 这个 silo 没拆 —— 包已经处于”几乎被卸载”的状态,用户态 API Get-AppxPackage 已经看不到它,但 silo 还挂在内核里霸着 hive 文件。所有的 0x20 锁都是 silo 持有的。
Silo 没有用户态 API 直接拆。能拆 silo 的只有:
- 正常的
Remove-AppxPackage流程(已经失败了,因为 chrome-native-host 的阻塞留下了不一致状态) - 重启
cexecsvc(Container Execution Service)—— 会影响机器上所有 MSIX 应用,包括 Notepad、WidgetsPlatformRuntime、Shell 扩展等 - 重启机器
机器是服务器,能不重启就不重启。我又绕了半小时试各种 Add-AppxPackage -Register 的花活,没能绕过来。最后还是重启了。
第三层:重启后的新错误
重启后 silo 拆干净了,reg query hivelist 看不到 Claude 条目。应该能装了吧。
Add-AppxPackage : 部署失败,原因是 HRESULT: 0x80073CF6, 无法注册包。错误 0x80070005: 在处理请求时,由于以下错误,系统无法注册 windows.service 扩展: 拒绝访问。错误变了。0x80070005 ACCESS_DENIED 出现在注册 windows.service 扩展这一步 —— MSIX 包里声明了一个 packaged service,部署引擎要把它创建成系统服务。日志前后几行看,签名验证通过了,文件解压完了,PackagedServiceDEH EvaluateRequest 成功了,就是在最终 Commit 那步被拒。
能在这个点拦的只有 HIPS / 主动防御类产品。机器上跑着火绒,它的策略是:
- Microsoft 系统签名自动放行
- 默认拒绝未知发布者
- 对链追溯敏感 —— 即便当前操作方是
AppXSvc(SYSTEM 权限的系统组件),火绒也会追溯到真实发起者D:\Downloads\Claude Setup.exe,然后按发起者的信任级别判断
所以链条是:Claude Setup.exe(在 Downloads)→ 触发 AppXSvc → AppXSvc 试图注册系统服务 → 火绒追溯到 Downloads → 拒绝。
这套链追溯设计完全合理。如果”Microsoft 签名的系统服务可以替任意发起者做敏感操作”能用,那”从 Downloads 双击的东西通过 AppXSvc 注册服务”就成了通用绕过路径 —— 高级恶意软件确实是这么干的。自己不碰敏感操作,诱导系统组件代为执行。
请 admin 临时把火绒主动防御关了,一把装上。
真正的根因
时间线顺下来其实是这样:
T0: 系统稳定,Claude MSIX 正常跑着 chrome-native-host 作为 Chrome 扩展的长驻进程,持有包内文件
T1: Anthropic 推新版,MSIX 自更新触发 (自更新发起者是已安装的 Claude,位于 Program Files, 火绒放行,跟 Downloads 无关)
T2: AppXSvc 开始替换旧包文件 chrome-native-host 还活着,User.dat 删不掉 部署失败,回滚
T3: 回滚不干净 —— Chrome 扩展会把 host 重新拉起 silo 没拆,hive 文件持续被占用 包进入僵尸状态
T4: 用户发现 Claude 坏了,从 Downloads 下载安装器修复 T3 的残留还在 + 发起者在 Downloads 两层问题叠加,卡死
T5: 每次重试撞同一堵墙根因在 T1 → T2 这一步。Claude for Chrome 的架构决定了会有一个长驻的 native host 进程,它持有的文件正好是 MSIX 更新时必须替换的。只要用户的 Chrome 开着并启用了 Claude 扩展,MSIX 自更新就是一场豪赌 —— 赌的是更新触发的那一刻 Chrome 没在发消息给 host。赌输一次,就从 T2 走到 T3,再也回不去。
严格 HIPS + 我自己从 Downloads 装,只是放大器,把 “偶发的失败” 放大成了 “无论如何都回不去”。问题的根源在 T1 → T2 的架构性脆弱。
责任归属
今天这事有三方参与,各自处境不同。
火绒的策略没有问题。默认拒绝未知来源、签名验证、链追溯、对系统签名自动放行、fail-close 不超时放行 —— 这套是服务器场景下的标准姿势。为了装一个聊天工具去把策略改松,等于把策略的核心价值废掉,不划算。
微软的 MSIX 也没大问题。容器化隔离、hive 隔离、packaged service 这套设计在桌面应用分发场景下是有道理的。代价是部署流程对部分应用文件有独占需求。
Anthropic 的架构决策是问题所在。MSIX 自更新 + 长驻 native host + Chrome 扩展自动拉起 host —— 这三个特性组合起来,在任何用户的机器上都是定时炸弹,只是频率高低的差别。修法其实不难:
- 部署开始前主动给 Chrome 扩展发信号,让 host 优雅退出
- native host 改按需启动,不常驻
- 把 host 二进制放在 MSIX 包外(比如
%LOCALAPPDATA%),更新时根本不碰到
任何一个做了都不至于走到今天这局面。
我自己的处置
- 当前装好的 MSIX 版本先用着
- 关掉 Chrome 里的 Claude 扩展 —— 这一步立刻消除 host 持锁的可能性。如果将来 MSIX 自更新还是失败,至少不会陷入僵尸 silo 的死循环
- 版本冻结,不主动触发更新。真有新版本需求再走手动流程,关浏览器 → 手动升 → 打开浏览器
- 安装器今后放到受管路径(
C:\Installers\),不直接从Downloads跑 —— 这是火绒策略本来期望的流程
技术选型的摩擦点在这里看得很清楚:一个桌面 AI 客户端想把自己做得跟操作系统深度集成(packaged service + 浏览器扩展 + MSIX 分发),就得接受在严格环境下容易翻车。我的服务器是严格环境,那就用松的那套机制 —— Squirrel 版装在 %LOCALAPPDATA%,没有 AppX 部署、没有 silo、没有 packaged service,跟 Cowork 说再见但换来一个不会在半夜因为一次失败更新把自己锁死的 Claude。
下次重装走 Squirrel。