我叫 Koen,写代码写了将近 30 年,现在在洛杉矶做独立开发,客户项目和自己的产品都在做。这篇文章记录的是最近几天我在 Windows 上折腾 Claude Desktop 的完整过程——从一个看起来很普通的错误弹窗,到最后动用 Windows 内核对象、Job Object、AppX 容器这些底层知识才勉强绕过去。写出来,是因为我在排查过程中翻遍了 GitHub 上一堆 issue,发现遇到这个问题的人不少,但大部分讨论都零散、不完整,没人把整个决策链条讲清楚。希望这篇能帮后来的人少走弯路。
先把结论放在最前面:这是 Claude Desktop 在 Windows 上因为使用 MSIX 打包方式导致的一个已知未修复 bug,官方目前没有根治方案。我最后的解决办法是彻底放弃 MSIX 版本,改成官方仍在并行提供的传统 Squirrel(.exe)安装包,绕开触发这个 bug 的那套容器机制,才算恢复正常。 下面是完整过程,包括我踩过的坑和试过没用的方案,都如实记录。
先说一下我的使用习惯,这很关键
我的工作电脑常年不关机——这是我从业这么多年养成的习惯,也是刻意的选择。桌面上常年开着一堆终端、编辑器、后台服务、SSH 会话,很多是跨天甚至跨周持续运行的工作进程。我最讨厌的一件事就是 Windows 自作主张地自动更新、自动重启,每次都打断这些常驻进程,之后还得一个个手动拉起来,非常影响效率。所以我的机器上自动重启是关掉的,Claude Desktop 也是长期开着不关,跟其他工作窗口一样常驻在后台。
这个使用习惯直接决定了这次问题对我的影响方式,也决定了我为什么从一开始就排斥"重启电脑"这个方案——这不是因为我懒得重启,而是重启这件事对我来说代价很高:一堆需要手动恢复的进程和上下文,从一个老程序员的思维习惯来说,指望靠"重启大法"日常维持一个软件能用,是一件很反人类的事情。软件应该是可预期、可维护的,不应该需要用户靠玄学手段维持稳定。
问题是怎么被发现的
第一次出问题,是某天早上起床后走到电脑前,发现 Claude Desktop 的窗口已经不在了——它在我睡觉的这几个小时里自己关闭了,大概率是触发了一次后台自动更新。我手动点击图标想重新打开,跳出来一个 Windows 系统级的错误框:
另一程序正在使用此文件。
C:\Program Files\WindowsApps\Claude_1.37937.3.0_...
一个"确定"按钮,点了之后应用直接不启动。第一反应是某个进程占着文件没释放,干了这么多年这种问题见得多了,正常思路是:
- 任务管理器杀掉所有 Claude 相关进程
- 重新打开
试了,没用,同样的弹窗。既然报错里明确写了路径 C:\Program Files\WindowsApps\Claude_1.37937.3.0_...,我第一反应是自己去这个目录看看,到底是什么文件被占用了。结果打开资源管理器,在 C:\Program Files 底下压根找不到 WindowsApps 这个文件夹——凭经验知道它一定是被隐藏了,索性直接在地址栏里手打路径回车。
这下更离谱了:资源管理器直接弹窗说我没有权限访问这个文件夹。我当时是真的愣住了——我用的是管理员账户,本机最高权限,一个系统自带的路径,居然连"看一眼"的权限都没有。这跟我几十年积累的直觉完全不符:在我的认知里,管理员理应能访问本机上的任何路径,顶多是操作时弹个 UAC 确认。
带着这个疑惑我顺手查了一下 WindowsApps 这个文件夹到底是什么来路,发现它确实不简单:这个目录里存放的是所有通过 Microsoft Store / AppX 机制安装的应用包,它的所有者不是 Administrators 组,而是一个叫 TrustedInstaller 的特殊系统服务账户——权限层级上比本机管理员还要高。默认情况下,哪怕是管理员账户,对这个目录也只有极其有限的访问权限,微软这么设计是为了防止用户(或者恶意软件)手贱直接改动或删除商店应用的包文件,破坏应用的完整性校验。想真正进去看内容,得手动去"属性 → 安全 → 高级"里把所有者从 TrustedInstaller 改成自己的账户,而且社区里明确警告,改了之后如果不小心动了里面的文件,可能会连带搞坏商店应用的正常运作,事后最好再把所有者改回 TrustedInstaller。
这个发现在当时给我一个提醒:Claude 被装在了一个我作为管理员都无法随意触碰的特殊受保护区域里,这已经不是普通 Win32 程序"装在 Program Files 底下"那种朴素的文件系统关系了,背后一定有一套我还不了解的机制在管着它。这也是促使我后来认真去查 MSIX/AppX 这套体系的一个直接契机。
当时查到的零星资料大多是"重启电脑试试",考虑到我并不想为了一个应用去打断电脑上一堆常驻的工作进程,我先按上面这个思路自己摸索了一阵,但一时没查出结果,时间也紧,最后还是妥协重启了一次电脑。重启后问题消失,我没多想,以为是一次偶发的冲突。
问题复发:这次我下定决心不再靠重启解决
没过几天,同样的情况又出现了——早上过去看,Claude 又自己关掉了,同样的报错弹窗。这次我意识到:如果这个问题会反复出现,那"重启电脑"根本不是解决方案,只是一个治标不治本、而且代价很高的临时创可贴。对我这种电脑常年不关机、桌面上一堆工作进程的使用方式来说,靠定期重启来维持一个应用能打开,是完全不能接受的。这也是我这次决定彻底查清楚根因、动手系统排查的直接原因。
排查过程:一层一层往下扒
第一层:以为是 MSIX 更新时的文件锁
先查到的信息是,Claude Desktop 在 Windows 上是通过 MSIX 包分发的,错误路径 C:\Program Files\WindowsApps\Claude_... 也印证了这一点。MSIX 是微软的现代应用打包格式,更新时理论上要先完全退出旧版本才能替换文件。GitHub 上 anthropics/claude-code 仓库确实有对应的 issue(#66497)在报告"Relaunch to Update"点了之后卡在这个报错上,说是旧进程没释放文件锁。
按这个思路,我在管理员 PowerShell 里彻底清理进程:
Get-Process | Where-Object { $_.ProcessName -match "claude|cowork" } | Stop-Process -Force
没用。而且我发现有个细节:任务管理器里根本没有任何进程在占用这个安装目录下的文件——这个"文件被占用"的提示本身就有问题。
第二层:真正的元凶是 AppX 容器层,不是文件锁
继续往下查,找到了几个更硬核的 issue(#53247、#61635、#73107),里面有开发者动用了 Sysinternals 的 handle.exe 和 Process Explorer 去实测——确认没有任何用户空间进程锁定这个文件。真正的故障发生在 Windows 的 AppX/Desktop Bridge 容器层:Windows 事件查看器里能看到:
Event ID 215: 0x80070020: cannot create the Desktop AppX container for package Claude_<版本>_x64__pzs8sxrjxfjjc due to an error converting the job
Event ID 208: 0x80070020: cannot create the process for package ... due to an error setting up the runtime
0x80070020 = ERROR_SHARING_VIOLATION,出现在 Job Object 转 Silo(容器) 这一步。也就是说,Claude 这个应用被打包进了一个隔离容器里运行(这是 MSIX/Desktop Bridge 的标准做法),每次启动都要创建一个专属容器,而这次创建失败了,Windows 把这个失败硬套上了"文件被占用"这句通用提示——这句话是错的,具有很强的误导性,我一开始按"文件锁"的思路排查完全是被这句话带偏了。
这对我来说是这次排障里最有价值的一个认知:系统弹窗给出的错误文案,未必是真实的故障层级,尤其是跨了几层抽象(AppX 容器 → Win32 错误码 → 通用提示文案)之后,信息损耗很严重。真正定位问题,得看事件查看器里的原始 Event ID,而不是弹窗文字。
第三层:内核对象的引用计数,以及谁在钉着它不放
再往下查,issue #61635 里有个开发者给出了完整的技术链条,这也是这次让我觉得最长见识的部分:
Windows 的内核对象(Job Object 也是其中一种)是引用计数的——只要还有任何进程或服务持有它的句柄,这个对象就不会被销毁,哪怕它已经从对象管理器的命名空间里"消失"了。这次的具体情况是:
- Claude 的应用容器命名是固定规则,比如
Container_Claude_<版本号>_<用户SID> - 之前我用 Claude 触发过需要 UAC 提权的操作,Windows 负责处理提权弹窗的 AppInfo(Application Information)服务打开了一个指向这个容器 Job 对象的句柄
- Claude 退出、或者应用更新到新版本之后,AppInfo 服务从来没有释放这个句柄——一个典型的句柄泄漏
- 于是这个"僵尸"对象靠着 AppInfo 那一个引用一直活在内核里,占着命名槽位
- 下次启动想创建同名新容器时,跟这个还没死透的旧对象撞名,触发
ERROR_SHARING_VIOLATION
重启电脑之所以有效,是因为重启会强制终止所有进程和服务,句柄归零,内核才真正把这个僵尸对象销毁、腾出槽位。但正如前面说的,重启对我来说代价太高,我需要一个不用重启的办法。
尝试绕开重启:几次不成功的努力
搞清楚原理之后,我试了几个方向,都是冲着"不碰重启、不碰登出"这个前提去的:
尝试 1:单独重启 AppInfo 服务(既然是它持有的泄漏句柄,直接重启它理论上该有等价效果):
Restart-Service -Name Appinfo -Force
结果:
Restart-Service : 服务"Application Information (Appinfo)"停止失败。
后来才明白,AppInfo 这个服务被 Windows 设计成不允许手动停止——它本身是"允许其他东西提权"的守门人,如果能被随手停掉,会陷入"想停 AppInfo 得先提权、但提权又依赖 AppInfo"的死锁。论坛上能看到不少人误禁用它之后,整台电脑所有需要管理员权限的操作全部失效,得进安全模式才能救回来。这条路彻底堵死。
尝试 2:重启 AppXSVC / ClipSVC(更通用的 AppX 部署服务):
Restart-Service -Name AppXSVC -Force
Restart-Service -Name ClipSVC -Force
这个能执行,但没解决问题——因为这次的根因是 Claude 应用自己在某次崩溃/更新时没清理好容器状态,不是这两个通用服务本身出了故障,其他 AppX 应用(记事本、OneDrive、Store 应用)在同一时间窗口都能正常创建容器,说明系统级服务本身没坏。
尝试 3:注销 Windows 账户而不是重启——社区里有反馈说注销效果等同重启,因为很多会话级状态会跟着清空。但对我来说,我电脑上常年开着一堆工作窗口和进程,注销的代价跟重启没什么本质区别,一样要手动恢复一堆上下文,这条路对我不现实,直接放弃。
到这一步,我确认了:这是 Anthropic 需要在代码层面修的 bug(在启动/崩溃路径上没有可靠地释放容器句柄),社区目前没有能在系统层面安全绕开的手段,GitHub 上对应的核心 issue(#53247)截至我写这篇文章时仍然是 Open 状态。
换个思路:既然是 MSIX 容器机制的锅,那就不用 MSIX
想明白这一层之后,思路变了——与其在系统层面跟这个 bug 纠缠,不如换一个根本不会触发这套容器机制的安装方式,从源头避开问题,而不是每次发作了再去救火。
查证后发现:Claude Desktop 在 Windows 上其实有两条并行的分发线:
- .msix:2026 年 2 月上线 Cowork 功能时切换过来的"现代"安装方式,带 Cowork 功能,但也带着这套容器机制和它的 bug
- .exe(Squirrel 框架):更早期、更传统的安装方式,不走 AppX 容器,但不支持 Cowork
我不用 Cowork,只用 Claude Code 做日常开发辅助,这两者互不依赖,所以换成 Squirrel 版本对我来说没有任何功能损失。
第一次尝试:winget,卡住不动
winget install --id Anthropic.Claude -e
跑了很久没有任何输出,怀疑是隐藏的协议确认提示卡住了,加参数重试:
winget install --id Anthropic.Claude -e --accept-package-agreements --accept-source-agreements
依然没反应。排查了 winget source reset --force、检查有没有残留的 winget 进程、有没有待处理的系统更新——都没解决,最后放弃 winget,直接找官方的直链。
第二次尝试:直链下载,撞上 Cloudflare 人机验证
找到官方的 Squirrel 版直链重定向地址:
https://claude.ai/api/desktop/win32/x64/exe/latest/redirect
用命令行工具直接拉取:
Invoke-WebRequest -Uri "https://claude.ai/api/desktop/win32/x64/exe/latest/redirect" -OutFile "$env:USERPROFILE\Downloads\ClaudeSetup.exe"
返回的不是安装包,是一段 Cloudflare 人机验证挑战页面的 HTML/JS——命令行工具没有 JS 引擎,过不了这层验证。
最终方案:直接用浏览器打开这个链接
放弃命令行,把这个链接直接粘贴到浏览器地址栏,浏览器正常完成人机验证,触发下载,拿到真正的安装包。双击运行,静默安装,全程没有弹出 UAC 提权框——这也侧面印证了它走的确实是不需要容器化、不需要额外提权的传统 Squirrel 路径。
验证安装结果:
Get-ChildItem "$env:LOCALAPPDATA" -Filter "*claude*" -ErrorAction SilentlyContinue
Get-ChildItem "$env:LOCALAPPDATA" -Filter "*anthropic*" -ErrorAction SilentlyContinue
确认落在 %LOCALAPPDATA%\AnthropicClaude 下面,是 Squirrel 结构。
终于能用了,而且这次不用重启
换成 Squirrel 版本之后,Claude Desktop 终于正常打开了——这次没有靠重启解决,是从安装方式的根源上绕开了那套容器机制。对我这种不喜欢重启、电脑常年挂着一堆工作进程的使用方式来说,这才是真正意义上"解决"了问题,而不是又一次靠运气把故障暂时压下去。
登录进去,普通聊天记录完好——这个数据本来就存在服务器端,跟本地装什么版本没关系。
但打开 Claude Code 相关的历史会话时,看到的是这样的提示:
Can't reach your computer
It may be asleep or offline. This session will reconnect when it's back.
Remote Control host unreachable (computer_unreachable)
这是 Claude Code 的 Remote Control(远程控制)功能——它允许你从手机或网页接续电脑上正在跑的本地会话,但前提是电脑上那个具体的进程要一直活着。这几天我反复折腾(卸载、重装、还有中间那次不情愿的重启),原来承载会话的那个本地进程早就被终止过好几次了,会话记录还在(历史数据没丢),但作为"远程宿主"的连接已经彻底断了,不会自动恢复——这不是网络问题,是压根没有活的进程可连。
想继续用,得回到电脑上用 claude --resume 重新接上历史会话,如果还要用远程控制,得在新起的会话里重新执行一次 /remote-control,建立新的远程连接。这算是这次折腾里一个没能完全避免的代价,记在这里供大家心理有数。
写给同样遇到这个问题的你
如果你也在 Windows 上碰到"另一程序正在使用此文件"这个报错,指向 C:\Program Files\WindowsApps\Claude_...,这是我总结下来的建议顺序:
- 先别急着重启,试试杀掉所有 Claude/cowork 相关进程后重新打开,小概率能解决
- 如果你之前在 Claude 里做过需要提权的操作,去任务管理器"详细信息"页找找有没有异常的孤儿子进程,杀掉可能有效,不用碰重启
- 如果你不需要 Cowork,只用 Claude Code 或普通聊天,直接换成 Squirrel 版本是目前最彻底的绕开方案:卸载 MSIX 版本 → 浏览器打开
https://claude.ai/api/desktop/win32/x64/exe/latest/redirect→ 手动下载安装 - 换版本前记得备份
%USERPROFILE%\.claude\projects\这个目录,虽然理论上重装不会碰它,但多一层保险总没错 - 心理预期要放对:这是 Anthropic 那边的产品 bug,不是你的系统或操作有问题,也没有你能在自己电脑上"根治"的办法,能做的只是绕开触发条件
- 如果你跟我一样电脑常年不关机、讨厌自动重启,那这次的经验对你会特别有参考价值——靠重启解决反复发作的问题,从来不是真正的解决方案,找到根因、换一条不触发 bug 的路径,才是值得花时间的方向
- 如果你依赖 Remote Control 远程接续 Code 会话,注意这类系统层面的折腾(重启、重装)都会打断当前的远程连接,回到电脑本地手动
resume就行,数据不会丢
写了 30 年代码,这种问题最打击人的地方从来不是解决它本身有多难,而是"系统给你的错误提示是错的"——你得先自己证伪表面的说法,才能找到真正值得深挖的方向。这次从"文件占用"查到"内核对象引用计数",绕了不少路,但每一层查下去都有真实的技术依据可以验证,这也是我愿意花时间写这篇文章的原因:希望能帮后面遇到同样问题的人,跳过我踩过的那几个弯路,也少一次不必要的重启。