← 回到书架纸上留痕 · 文档阅读

排查指南

Codex Windows 无窗口启动故障排查指南

围绕 Windows 桌面端启动后只有后台进程、没有可见窗口这一现象整理的排查与修复记录。

阅读
24 min
更新
2026.09.12
来源
pdf
分类
Windows
页数
19
原文件
查看 / 下载 PDF
  • Codex
  • Windows
  • 故障排查

从这里开始,慢慢读。

这是从公开 PDF 提取并重新排版的阅读版本;复杂版式、图片与原始分页仍可通过原文件查看。

1

title: "Codex Windows 启动后只有后台进程、没有窗

口:排查与修复指南"

author: "社区故障记录 / Workaround"

date: "2026-09-12"

适用场景

本文适用于 Codex / ChatGPT Windows 桌面版出现以下典型现象时:

点击启动后没有任何可⻅窗口;

任务管理器里能看到多个 ChatGPT.exe ;

这些进程⻓期存活,甚至持续占用 CPU / 内存;

MainWindowHandle = 0 、MainWindowTitle 为空;

进程树里可以看到 GPU、NetworkService、StorageService、Crashpad,但 没有 --

type=renderer ;

重装、Repair / Reset、清理 Chromium profile 后仍然复现;

%LOCALAPPDATA%\OpenAI\Codex\runtimes\cua_node 下不断出现 .staging-* 目录。

  • *一句话概括:**安装包本身通常是完整的,但 Codex 第一次启动或版本更新后,需要把随

MSIX 安装包附带的 cua_node runtime 从 WindowsApps 搬到用戶目录。某些 Windows

环境下,这个 relocation / staging 过程会在复制受保护文件时失败,留下半成品 runtime,

最终导致 app-server / renderer 没有启动,桌面窗口也就不会出现。

已验证案例

本文方法已在以下环境中实际验证:

Codex Windows Stable:26.908.4834.0

平台:Windows 11 x64

MSIX package:OpenAI.Codex

2

该版本安装包中的官方 cua_node runtime:

SourceFiles : 4123

Manifest : True

NodeExe : True

NodeRepl : True

但自动 staging 后出现:

StagingFiles : 517

MissingFiles : 3606

NodeExe : True

NodeRepl : False

手工使用 xcopy /G 将当前版本完整 runtime 放到正确的 content-addressed runtime 目录后:

Copied 4123 files

XCOPY exit code: 0

SourceFiles : 4123

TargetFiles : 4123

Manifest : True

NodeExe : True

NodeRepl : True

Missing files: 0

Extra files: 0

随后 Codex 立即正常启动并显示 GUI。

为什么会发生

Microsoft Store / MSIX 包中的部分文件可能带有 Windows 的 Application Protected 属性。

典型例子是:

3

bin\node_repl.exe

这类文件从:

C:\Program Files\WindowsApps\...

复制到普通用戶目录时,并不总能使用普通文件复制语义。已有公开报告显示,普通 Copy-Item

/ Node copyfile 可能返回:

The specified file could not be encrypted.

HRESULT: 0x80071770

而 Windows 的:

xcopy /G

允许“加密 / Application Protected 源文件复制到解密后的普通目标位置”,因此可以完成这一

步。

Codex 当前某些 Windows 版本的 runtime materialization 流程没有可靠处理这种失败,于是会

形成:

4

完整 MSIX runtime

|

v

创建 .staging-<runtime-id>-<random>

|

v

复制一部分文件

|

v

遇到 Application Protected 文件 -> 失败

|

v

staging 未完成 / 未 finalize

|

v

app-server / renderer 未启动

|

v

ChatGPT.exe 挂在后台,但没有窗口

  • *因此:重装往往无效。**重装只是重新获得一份完整 MSIX 包;下一次启动仍然会再次走同一套

有问题的 relocation 流程。

第一步:确认是否属于同一类故障

先正常启动 Codex,等十几秒,然后打开 PowerShell 7。

  • 检查窗口句柄

Get-Process ChatGPT |

Select Id, CPU, WorkingSet, Responding, MainWindowHandle,

MainWindowTitle

如果多条进程都是:

5

Responding : True

MainWindowHandle : 0

MainWindowTitle :

说明进程确实起来了,但没有创建正常顶层窗口。

  • 检查进程类型

$pkg = Get-AppxPackage OpenAI.Codex

Get-CimInstance Win32_Process |

Where-Object {

$_.ExecutablePath -like "$($pkg.InstallLocation)*"

} |

Select ProcessId, Name, CommandLine |

Format-List

故障状态常⻅:

ChatGPT.exe

ChatGPT.exe --type=crashpad-handler

ChatGPT.exe --type=gpu-process

ChatGPT.exe --type=utility --utility-sub-

type=network.mojom.NetworkService

ChatGPT.exe --type=utility --utility-sub-

type=storage.mojom.StorageService

但看不到:

ChatGPT.exe --type=renderer

这时继续检查 runtime。

第二步:检查 cua_node staging 是否残缺

6

运行:

$runtimeRoot = "$env:LOCALAPPDATA\OpenAI\Codex\runtimes\cua_node"

Get-ChildItem $runtimeRoot -Directory -Force -ErrorAction

SilentlyContinue |

Sort-Object LastWriteTime -Descending |

ForEach-Object {

[PSCustomObject]@{

Name = $_.Name

Files = (Get-ChildItem $_.FullName -Recurse -File -Force -

ErrorAction SilentlyContinue).Count

NodeExe = Test-Path "$($_.FullName)\bin\node.exe"

NodeRepl = Test-Path "$($_.FullName)\bin\node_repl.exe"

}

}

如果看到大量类似:

.staging-a708e72b10c27b59-XXXXXX 517 True False

.staging-a708e72b10c27b59-XXXXXX 3450 True False

.staging-xxxxxxxxxxxxxxxx-XXXXXX 93 True False

尤其是:

NodeExe = True

NodeRepl = False

就与本文故障高度吻合。

注意:不同 Codex 版本的 runtime ID 和完整文件数会变化。不要照抄本文的

a708e72b10c27b59 或 4123 ,应以你当前版本实际检测结果为准。

7

第三步:确认安装包里的官方 runtime 是完整

$pkg = Get-AppxPackage OpenAI.Codex

$srcRoot = Join-Path $pkg.InstallLocation "app\resources\cua_node"

[PSCustomObject]@{

PackageVersion = $pkg.Version

SourcePath = $srcRoot

SourceExists = Test-Path $srcRoot

Files = (Get-ChildItem $srcRoot -Recurse -File -Force -

ErrorAction SilentlyContinue).Count

NodeExe = Test-Path "$srcRoot\bin\node.exe"

NodeRepl = Test-Path "$srcRoot\bin\node_repl.exe"

}

理想状态:

SourceExists : True

NodeExe : True

NodeRepl : True

如果安装包里的 node_repl.exe 本身都不存在,就不要继续使用本文方法。

第四步:自动识别当前 runtime ID

使用最新的 .staging-* 目录来识别当前版本期待的 runtime ID:

8

$runtimeRoot = "$env:LOCALAPPDATA\OpenAI\Codex\runtimes\cua_node"

$latestStaging = Get-ChildItem $runtimeRoot -Directory -Force |

Where-Object { $_.Name -like ".staging-*" } |

Sort-Object LastWriteTime -Descending |

Select-Object -First 1

if (-not $latestStaging) {

throw " 没有找到 .staging-* 目录,本文方法可能不适用于当前故障。 "

}

if ($latestStaging.Name -notmatch '^\.staging-([0-9a-fA-F]+)-') {

throw " 无法从 staging 目录名解析 runtime ID : $($latestStaging.Name)"

}

$runtimeId = $Matches[1]

$runtimeId

输出示例:

a708e72b10c27b59

第五步:执行修复

  • *安全说明:**下面操作不会修改 WindowsApps 中的官方安装包,只会把官方包内现成的

runtime 复制到当前用戶的 runtime cache。建议保留 .staging-* ,等确认修复成功后再

清理。

  • 彻底停止当前 Codex / ChatGPT 进程
9

$pkg = Get-AppxPackage OpenAI.Codex

Get-CimInstance Win32_Process |

Where-Object {

$_.ExecutablePath -like "$($pkg.InstallLocation)*"

} |

ForEach-Object {

Stop-Process -Id $_.ProcessId -Force -ErrorAction SilentlyContinue

}

Start-Sleep -Seconds 3

确认没有残留:

Get-CimInstance Win32_Process |

Where-Object {

$_.ExecutablePath -like "$($pkg.InstallLocation)*"

}

应当没有输出。

  • 设置源目录和目标目录

$srcRoot = Join-Path $pkg.InstallLocation "app\resources\cua_node"

$runtimeRoot = "$env:LOCALAPPDATA\OpenAI\Codex\runtimes\cua_node"

$target = Join-Path $runtimeRoot $runtimeId

如果 $target 已存在但怀疑不完整,建议先备份:

if (Test-Path $target) {

$backup = "$target.backup-$(Get-Date -Format 'yyyyMMdd-HHmmss')"

Rename-Item $target $backup

Write-Host "Existing target backed up to: $backup"

}

创建目标目录:

10

New-Item -ItemType Directory -Path $target -Force | Out-Null

  • 使用 xcopy /G 复制完整 runtime

xcopy "$srcRoot\*" "$target\" /E /H /K /G /Y /I

参数说明:

/E 复制所有子目录,包括空目录

/H 包含隐藏文件和系统文件

/K 保留文件属性

/G 允许加密 / 受保护源文件复制到解密目标

/Y 覆盖时不再询问

/I 将目标视为目录

如果最后显示:

XXXX File(s) copied

并且:

XCOPY exit code: 0

即可进入验证阶段。

第六步:完整验证

不要仅检查 node_repl.exe 是否存在。建议同时验证:

  • 源 / 目标文件数量;
  • 相对路径集合是否一致;
  • 关键文件 SHA-256 是否一致。

运行:

11

$srcFiles = Get-ChildItem $srcRoot -Recurse -File -Force

$dstFiles = Get-ChildItem $target -Recurse -File -Force

$srcRelative = $srcFiles | ForEach-Object {

$_.FullName.Substring($srcRoot.Length).TrimStart('\')

}

$dstRelative = $dstFiles | ForEach-Object {

$_.FullName.Substring($target.Length).TrimStart('\')

}

$diff = Compare-Object $srcRelative $dstRelative

$missing = $diff |

Where-Object { $_.SideIndicator -eq '<=' } |

Select-Object -ExpandProperty InputObject

$extra = $diff |

Where-Object { $_.SideIndicator -eq '=>' } |

Select-Object -ExpandProperty InputObject

[PSCustomObject]@{

SourceFiles = $srcFiles.Count

TargetFiles = $dstFiles.Count

Manifest = Test-Path "$target\manifest.json"

NodeExe = Test-Path "$target\bin\node.exe"

NodeRepl = Test-Path "$target\bin\node_repl.exe"

MissingFiles = $missing.Count

ExtraFiles = $extra.Count

}

关键文件 Hash:

12

$keyFiles = @(

"manifest.json",

"bin\node.exe",

"bin\node_repl.exe"

)

foreach ($file in $keyFiles) {

$src = Join-Path $srcRoot $file

$dst = Join-Path $target $file

[PSCustomObject]@{

File = $file

Match = ((Get-FileHash $src -Algorithm SHA256).Hash -eq

(Get-FileHash $dst -Algorithm SHA256).Hash)

}

}

理想结果:

SourceFiles = TargetFiles

Manifest = True

NodeExe = True

NodeRepl = True

MissingFiles = 0

ExtraFiles = 0

并且关键文件全部:

Match = True

第七步:启动验证

正常从开始菜单启动 Codex。

如果修复命中,通常会出现明显变化:

13

GUI 正常显示;

ChatGPT.exe --type=renderer 出现;

Codex app-server 正常启动;

MainWindowHandle 不再全部为 0。

建议成功后:

  • 正常关闭 Codex;
  • 再次启动一次;
  • 确认第二次仍能正常打开。

一键修复脚本(适合已经确认故障指纹的用

戶)

运行前请先确认本文前面的故障指纹与你一致。脚本会自动读取当前 MSIX、最新 staging 的

runtime ID,并复制当前官方 runtime。

14

$ErrorActionPreference = "Stop"

$pkg = Get-AppxPackage OpenAI.Codex

if (-not $pkg) {

throw " 未找到 OpenAI.Codex MSIX 包。 "

}

$srcRoot = Join-Path $pkg.InstallLocation "app\resources\cua_node"

$runtimeRoot = "$env:LOCALAPPDATA\OpenAI\Codex\runtimes\cua_node"

if (-not (Test-Path $srcRoot)) {

throw " 官方 cua_node runtime 不存在: $srcRoot"

}

$latestStaging = Get-ChildItem $runtimeRoot -Directory -Force |

Where-Object { $_.Name -like ".staging-*" } |

Sort-Object LastWriteTime -Descending |

Select-Object -First 1

if (-not $latestStaging) {

throw " 没有找到 .staging-* ,无法自动识别 runtime ID 。 "

}

if ($latestStaging.Name -notmatch '^\.staging-([0-9a-fA-F]+)-') {

throw " 无法解析 runtime ID : $($latestStaging.Name)"

}

$runtimeId = $Matches[1]

$target = Join-Path $runtimeRoot $runtimeId

Write-Host "Package version: $($pkg.Version)"

Write-Host "Runtime ID: $runtimeId"

Write-Host "Source: $srcRoot"

Write-Host "Target: $target"

# 停止当前包中的所有进程

Get-CimInstance Win32_Process |

15

Where-Object { $_.ExecutablePath -like "$($pkg.InstallLocation)*" } |

ForEach-Object {

Stop-Process -Id $_.ProcessId -Force -ErrorAction SilentlyContinue

}

Start-Sleep -Seconds 3

$left = Get-CimInstance Win32_Process |

Where-Object { $_.ExecutablePath -like "$($pkg.InstallLocation)*" }

if ($left) {

throw " 仍有 Codex / ChatGPT 进程未退出。 "

}

# 若目标已存在则备份

if (Test-Path $target) {

$backup = "$target.backup-$(Get-Date -Format 'yyyyMMdd-HHmmss')"

Rename-Item $target $backup

Write-Host "Old target backed up: $backup"

}

New-Item -ItemType Directory -Path $target -Force | Out-Null

# 复制官方 runtime ; /G 是关键

xcopy "$srcRoot\*" "$target\" /E /H /K /G /Y /I

$xcopyCode = $LASTEXITCODE

if ($xcopyCode -gt 1) {

throw "XCOPY failed, exit code: $xcopyCode"

}

# 验证

$srcFiles = Get-ChildItem $srcRoot -Recurse -File -Force

$dstFiles = Get-ChildItem $target -Recurse -File -Force

$srcRelative = $srcFiles | ForEach-Object {

$_.FullName.Substring($srcRoot.Length).TrimStart('\')

16

}

$dstRelative = $dstFiles | ForEach-Object {

$_.FullName.Substring($target.Length).TrimStart('\')

}

$diff = Compare-Object $srcRelative $dstRelative

$missing = @($diff | Where-Object { $_.SideIndicator -eq '<=' })

$extra = @($diff | Where-Object { $_.SideIndicator -eq '=>' })

$ok = (

$srcFiles.Count -eq $dstFiles.Count -and

$missing.Count -eq 0 -and

$extra.Count -eq 0 -and

(Test-Path "$target\manifest.json") -and

(Test-Path "$target\bin\node.exe") -and

(Test-Path "$target\bin\node_repl.exe")

)

Write-Host ""

Write-Host "SourceFiles : $($srcFiles.Count)"

Write-Host "TargetFiles : $($dstFiles.Count)"

Write-Host "Missing : $($missing.Count)"

Write-Host "Extra : $($extra.Count)"

Write-Host "Manifest : $(Test-Path "$target\manifest.json")"

Write-Host "NodeExe : $(Test-Path "$target\bin\node.exe")"

Write-Host "NodeRepl : $(Test-Path "$target\bin\node_repl.exe")"

if ($ok) {

Write-Host ""

Write-Host "RUNTIME VERIFY PASSED. 现在可以正常启动 Codex 。 "

} else {

throw "Runtime verification failed. 暂时不要启动 Codex 。 "

}

17

更新后会不会再次出现

有可能。

Codex 的 cua_node 内容更新后,content-addressed runtime ID 也可能改变。

例如:

旧版本 runtime ID -> 440c4f095d41ea30

新版本 runtime ID -> a708e72b10c27b59

旧 runtime 即使完整,也不能替代新版本所需 runtime。

因此,如果官方尚未修复 relocation 逻辑,那么每次更新到新的 runtime ID 后,都可能再次出

现:

后台进程存在

+ 无 GUI

+ 无 renderer

+ 新 .staging-* 不断出现

+ NodeExe=True / NodeRepl=False

此时重新执行本文方法即可。

成功后是否可以删除 .staging-*

建议先确认:

  • Codex 能正常启动;
  • 关闭后再次启动仍正常;
  • 当前正式 runtime 目录完整存在。

然后可以考虑清理旧的 .staging-* 半成品目录以回收空间。

不要删除当前已经正常工作的正式 runtime ID 目录。

如果某些 staging 目录提示文件正在被占用,请先完全退出 Codex / ChatGPT 再操作。

18

不建议优先折腾的方向

如果你的故障指纹与本文一致,以下操作通常不是根因修复:

反复卸载 / 重装;

重置 Chromium profile;

清登录状态;

重装 WebView2;

反复更新显卡驱动;

强行 ShowWindow() ;

只补一个旧版本的 runtime;

从网上下载第三方 runtime 覆盖。

本文 workaround 使用的是 当前已安装官方 MSIX 包中自带的 runtime,不需要下载任何第三方

二进制。

公开 Issue 参考

本文现象与以下公开报告高度相关:

当前验证案例:openai/codex#45000

https://github.com/openai/codex/issues/45000

openai/codex#41540 - Application Protected node_repl.exe relocation failure /

0x80071770

https://github.com/openai/codex/issues/41540

openai/codex#41654 - runtime relocation / staging failure,完整 runtime 手工恢复后

GUI 正常

https://github.com/openai/codex/issues/41654

openai/codex#42501 - 26.901.x 中同类 cua_node staging 问题,xcopy /G

workaround

https://github.com/openai/codex/issues/42501

openai/codex#40843 - WindowsApps / Application Protected 文件 relocation 与

ERROR_ENCRYPTION_FAILED

https://github.com/openai/codex/issues/40843

19

最后总结

如果只记一件事:

Codex Windows 版“后台进程正常,但没有窗口”不一定是 Electron / GPU / profile 问

题。

如果同时存在大量残缺 .staging-* ,尤其 node.exe 已复制而 node_repl.exe 缺失,

那么很可能是 MSIX 中 Application Protected runtime 向用戶目录 relocation 失败。

核心修复逻辑:

识别当前 runtime ID

  • >

停止 Codex

  • >

从当前官方 MSIX 包读取完整 app\resources\cua_node

  • >

使用 xcopy /G 复制到正确的 runtime ID 目录

  • >

验证文件数 / 路径 / Hash

  • >

重新启动 Codex

在已验证案例中,完成这一过程后 Codex 秒启恢复正常。