Skip to content

Offer a current VC++ runtime in the game prefix for USVFS 0.5.7+ - #66

Merged
skjiisa merged 1 commit into
mainfrom
prefix-vc-runtime
Oct 3, 2026
Merged

skjiisa merged 1 commit into
mainfrom
prefix-vc-runtime

Conversation

@skjiisa

@skjiisa skjiisa commented Oct 3, 2026

Copy link
Copy Markdown
Owner

Why

From 0.5.7, USVFS links the VC++ runtime dynamically (0.5.6.1, shipped with MO2 2.5.2, had it built in). MO2 injects USVFS into the programs it starts, so it uses their runtime: the game folder's, or the Proton prefix's system32. A Skyrim prefix usually has the 2016 msvcp140.dll from the game's own redistributable plus Wine's built-in vcruntime140_1.dll. On a Steam Frame with ModOrganizer2/usvfs#93's 0.5.7.2 build, Skyrim and Explorer++ started from MO2 died right after inithooks called, with a jump to address 0 inside vcruntime140_1.dll. Installing Microsoft's redistributable into the prefix fixed it, and modded Skyrim then ran. #60's copy next to ModOrganizer.exe can't reach the game process. This matters on every platform once MO2 ships USVFS 0.5.7+, and on the Frame as soon as #93 lands.

What

  • Detect (vcruntime.prefix_runtime_problems, usvfs_needs_prefix_runtime): only when the instance's usvfs_x64.dll is 0.5.7+, and any of msvcp140/vcruntime140/vcruntime140_1 is missing, Wine's built-in stand-in (marker in its DOS stub), or older than 14.40. On the Frame's pre-install prefix the old vcruntime140_1 reported 14.42 but was Wine's, so version alone isn't enough.
  • Offer: a warning row with "Install Visual C++ runtime…" in the dashboard's MO2 card, only when needed, behind a confirmation dialog. Never automatic.
  • Install (service.install_prefix_runtime): back up the runtime DLLs to data/modsync/backups/, fetch the pinned and checksummed VC_redist.x64.exe (same pin as Give MO2 its own current Visual C++ runtime before launching it #60, cached), and run /install /quiet /norestart through the game's Proton and Steam Linux Runtime via the new launch.run_in_prefix (with flatpak-spawn --host from the Flatpak). Then re-check. It refuses while MO2 runs, and failures name the backup.
  • doctor: each instance's USVFS version, plus this check for 0.5.7+.

Testing

  • Unit tests: detection (old, stand-in, missing, current), the USVFS version threshold, the backup selection, and the install flow (success, installer failure, still old afterwards, refusing while MO2 runs).
  • uv run pytest -q: 362 passed, 18 skipped.
  • On the Frame: detection flags the real pre-install system32 backup and passes the current prefix. The real install path ran through Steam's ARM64 Proton from source and from inside the aarch64 Flatpak (about 15 s each, clean re-check, backups written). doctor shows usvfs 0.5.6.1 and usvfs 0.5.7.2: game prefix has a current VC++ runtime for the two test instances.
  • Not tested: clicking through the dialog in the GUI (the row is hidden because this machine's prefix is already current).

🤖 Generated with Claude Code

From 0.5.7, USVFS links the VC++ runtime dynamically. MO2 injects it into the
programs it starts (the game, SKSE, tools), where it uses that process's
runtime: the game folder's or the prefix's system32. A Skyrim prefix usually
has the 2016 msvcp140.dll from the game's own redistributable plus Wine's
built-in vcruntime140_1.dll; there the injected USVFS dies on its first C++
exception (seen on a Steam Frame with usvfs#93's 0.5.7.2 build: Skyrim and
Explorer++ died right after `inithooks called`, with a jump to address 0 inside
vcruntime140_1.dll). The copy next to ModOrganizer.exe (#60) can't help there.

- vcruntime: detect the problem (msvcp140/vcruntime140/vcruntime140_1 missing,
  Wine's built-in stand-in, or older than 14.40) when the instance's
  usvfs_x64.dll is 0.5.7+; back up the runtime DLLs; cache the pinned,
  checksummed VC_redist.x64.exe.
- launch.run_in_prefix: run a Windows program to completion in the game prefix
  through the same Proton and Steam Linux Runtime as MO2 (flatpak-spawn from
  the Flatpak).
- service: prefix_runtime_problems() and install_prefix_runtime() (backup,
  /install /quiet /norestart, re-check; refuses while MO2 runs; exit codes
  0/3010/1638 are success).
- Dashboard: a warning row with "Install Visual C++ runtime…" in the MO2 card,
  only when needed, behind a confirmation. Nothing installs without a click.
- doctor: each instance's USVFS version and, for 0.5.7+, the prefix check.

Tested on the Frame: detection flags the pre-install prefix backup
(msvcp140/vcruntime140 14.0.24215.1, Wine's vcruntime140_1) and passes the
current prefix; the install path ran through Steam's ARM64 Proton both from
source and from inside the aarch64 Flatpak (about 15 s, clean re-check).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
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.

1 participant