Good question, and yes — there's a real mechanism behind this. Steam's "auto-install runtime redistributables" behavior comes from Steamworks' installscript.vdf system, not anything magical.
How the MSVC redist thing works
When you package a build in Steamworks (via SteamPipe), you can attach an
installscript.vdf to a depot/branch. This script runs during install/update on the client machine and can execute arbitrary setup binaries — most commonly:
Code:
"InstallScript"
{
"Run Process"
{
"vcredist"
{
"process 1"
{
"process" "vcredist_x64.exe"
"command" "/q"
"no cleanup" ""
}
}
}
}
You literally bundle the actual
vcredist_x64.exe /
vcredist_x86.exe (or the DirectX web installer, PhysX installer, etc.) as files in your depot, and the installscript tells Steam to run them silently with version-check flags so it doesn't reinstall every update. This is why you'll sometimes see "Installing Visual C++ Redistributable..." flash by in the Steam client during a game install — it's just running an EXE you shipped, gated by Steam's install pipeline.
So it's not Steam "knowing" your dependencies in any metadata sense — you are shipping the installer and Steam is just the delivery mechanism plus a hook to execute it at install-time.
Is there a Java equivalent?
Not really, no. There's no Steamworks-native "JRE dependency" concept. Games shipping on Steam that are Java-based (Minecraft being the famous edge case, though it predates/ignores this problem in its own weird way) generally do one of:
- Bundle a full JRE inside the depot, and launch via a wrapper/native launcher (or a shell script/batch file) that points at the bundled java.exe explicitly rather than relying on system PATH. This is by far the most common approach — tools like jpackage (built into modern JDKs) or Launch4j are used to produce a native-looking executable that bundles a minimal JRE image (often trimmed via jlink).
- Use the installscript.vdf mechanism to silently run a JRE installer, same trick as vcredist — technically possible, just uncommon because bundling is simpler and avoids polluting/depending on system Java state.
Bundling wins because you don't want your game's behavior to depend on whatever random JRE version (or vendor — Oracle vs Temurin vs Corretto) happens to be on the user's system, or whether they have Java installed at all.
What about .NET?
Depends heavily on which .NET and how you built it:
- .NET Framework (legacy, pre-.NET-5): This ships with Windows or via Windows Update in most modern cases, but older/specific versions (3.5, 4.x) sometimes aren't present. Same installscript.vdf trick applies — bundle the redist installer and run it silently on install, exactly like vcredist.
- .NET (Core) 5/6/7/8+, modern .NET: You have the option to publish as:
- Framework-dependent — small deploy, but requires the correct shared runtime on the user's machine. If missing, you'd need the installscript trick to run the runtime installer.
- Self-contained deployment (SCD) — bundles the entire runtime into your output folder, no dependency on what's installed system-side. This is the overwhelmingly preferred choice for Steam games for the same reason as Java: predictability. You can also combine this with single-file publish and trimming to cut down the bundle size somewhat.