Skip to content

fix(everest): 安装 Everest 前检查游戏是否在运行,并给文件占用的失败加恢复提示 - #89

Merged
std-microblock merged 1 commit into
std-microblock:masterfrom
std-external:fix/everest-install-require-game-closed
Oct 15, 2026
Merged

std-microblock merged 1 commit into
std-microblock:masterfrom
std-external:fix/everest-install-require-game-closed

Conversation

@std-external

Copy link
Copy Markdown
Contributor

问题

在 CeleMod 的 Everest 页面点「安装/更新 Everest」,如果游戏(或任何进程)还占着游戏目录里的原生库,安装会每次都在中途失败:

System.IO.IOException: The process cannot access the file
 '...\Celeste\lib64-win-x64\fmod64.dll' because it is being used by another process.
   at MiniInstaller.LibAndDepHandling.<SetupNativeLibs>g__CopyNativeLib|1_0(...) LibAndDepHandling.cs:line 88
   at MiniInstaller.LibAndDepHandling.SetupNativeLibs() LibAndDepHandling.cs:line 103
   at MiniInstaller.Program.StandardMode(String[] args) Program.cs:line 77
Installing Everest failed.

失败之后游戏也起不来了(下面的「影响」)。来源:群里有玩家报告,重启电脑后依旧每次失败。

原因

  1. Everest 更新路径不检查游戏是否在运行。 download_and_install_everest(src-tauri/src/backend.rs)直接下载 → 把整包解压覆盖游戏目录 → Command::new(MiniInstaller-win64.exe)(src-tauri/src/everest.rs 的 run_command)。同一个仓库里其它会写游戏目录的路径都有保护:本地包安装用 is_celeste_running() 直接拒绝,崩溃助手先调 stop_game_for_restart,MiaoNet 设置用 ensure_miaonet_game_stopped;只有这个命令没有。
  2. MiniInstaller 自己的保护在这个调用方式下不起作用。 InGameUpdaterHelper.WaitForGameExit() 只在游戏内更新器设置的 EVEREST_UPDATE_CELESTE_PID 存在时才动手;EnsureGameIsWriteable() 也只探测 Celeste.exe 和 Celeste.dll,lib64-win-x64 下的原生库不在范围内,所以占用直到 File.Copy 才炸出来。
  3. 失败后没有提示用户怎么恢复,用户只拿到 MiniInstaller 的原始 stderr;而此时游戏目录已经是「新 Celeste.Mod.mm.dll + 旧的打过补丁的 Celeste.dll」的半成品状态,MiniInstaller 重建 Celeste.dll/apphost 的步骤(Program.cs:99-127)都没跑到,游戏因此打不开。

改动

只动 src-tauri/src/backend.rs:

  • download_and_install_everest 命令在安装前用已有的 is_celeste_running() 判断,游戏在跑就直接失败并提示「请先退出 Celeste 再安装 Everest」。崩溃助手路径先 kill 了游戏,不受影响;测试模式的早退分支在检查之前,也不受影响。
  • 新增 with_file_in_use_hint():安装失败信息里出现 being used by another process / 另一个程序正在使用此文件 时,补一句「确认游戏已完全退出(任务管理器里没有 Celeste.exe)后重新安装一次 Everest」,并说明上一次中断留下的半成品会被这次安装覆盖(这正是「安装失败后游戏打不开」的解法)。

验证

  • 报错行号与 EverestAPI/Everest 源码逐行对应(LibAndDepHandling.cs:88/103、Program.cs:77),确认是标准模式安装器;
  • 用 gh release view stable-1.6623.0 --repo EverestAPI/Everest 下的 main.zip 核对了包内路径:main/everest-lib/lib64-win-x64/fmod64.dll 对应报错里的目标目录,包内没有 piton-runtime/、根目录也没有 FNA.dll(排除了其它几个可能的启动失败原因);
  • cargo check:
(本地 cargo check 结果,见下方评论)
  • 无 Windows 环境,未做端到端复现;本改动只是把「安装前必须先退游戏」这条已有约定补齐到这个路径,并补上失败提示。

The Everest install path downloads the package, extracts it over the game
directory and then runs MiniInstaller, but it never checked whether the game
was running. MiniInstaller's own guard (WaitForGameExit) is a no-op when it is
launched this way and EnsureGameIsWriteable only probes Celeste.exe and
Celeste.dll, so a process still holding a native library fails the install
half-way through with a raw IOException on lib64-win-x64\fmod64.dll, leaving
the game with a new Celeste.Mod.mm.dll but the old patched Celeste.dll.

Refuse early like the local package install path does, and append an
actionable hint to that file-in-use error.
@std-external
std-external force-pushed the fix/everest-install-require-game-closed branch from 98dc1e1 to 9847c03 Compare October 14, 2026 13:46
@std-external

Copy link
Copy Markdown
Contributor Author

cargo check(nightly,src-tauri)通过:

    Finished `dev` profile [unoptimized + debuginfo] target(s) in 2m 00s

cargo fmt --check 无 diff。

@std-microblock
std-microblock merged commit ba287df into std-microblock:master Oct 15, 2026
5 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants