-
Notifications
You must be signed in to change notification settings - Fork 0
Update and Uninstall
Both flows ship as standalone single-file exes that live next to WKVRCProxy.exe. Each can run when WKVRCProxy itself isn't, so they don't share its IPC; they load what they need from WKVRCProxy.Core directly.
Sources:
-
src/WKVRCProxy.Core/Services/AppUpdateChecker.cs— periodic version poll -
src/WKVRCProxy.Updater/Program.cs—updater.exe -
src/WKVRCProxy.Uninstaller/Program.cs—uninstall.exe -
.github/workflows/release.yml— produces the zip+SHA256 the updater consumes
In-process, runs alongside the engine.
- Reads local version from
version.txt. - GETs
https://api.github.com/repos/RealWhyKnot/WKVRCProxy/releases/latest. - Parses the tag (
tag_name), strips the leadingv, parses asSystem.Version. - If remote > local, fires
OnStatusChanged(UpdateStatus.UpdateAvailable, releaseUrl). - The UI shows a banner + modal in
App.vue; Settings → Maintenance has a manual Check now button.
AppUpdateChecker does not download or apply. It only signals.
Triggered by the user clicking Update now in the UI. The UI sends a LAUNCH_UPDATER IPC, the bridge spawns updater.exe, and the UI begins shutdown.
- Updater verifies
WKVRCProxy.exeexists in its install dir. - Reads current version from
version.txt. - Fetches the latest release JSON.
- If versions match, relaunches and exits (nothing to do).
-
Parses
SHA256: <hex>from the release notes and refuses to proceed if it's missing or malformed (exit code 12). The value is captured here so a malformed release surfaces before the user is asked to close VRChat. - Polls the single-instance mutex
Local\WKVRCProxy.UI.SingleInstancefor up to 30 s, waiting for the UI to fully exit. - Downloads
WKVRCProxy-<version>.zipto a temp directory. - Verifies the downloaded zip's SHA256 matches the value parsed in step 5. Mismatch is a hard fail (exit code 7) — the zip is never extracted.
- Extracts to a staging temp dir, rejecting any entry whose resolved path escapes the staging dir (Zip Slip guard, exit code 13). If the zip has a single top-level folder (likely), unwraps it.
- Renames the existing install dir aside as
<install>-old-<timestamp>. - Moves the staged payload into place.
- Schedules the old dir for delete via
cmd.exe /c timeout 3 && rmdir /s /q "<old>". - Relaunches
WKVRCProxy.exefrom the new install dir, exits.
The atomic-swap means a failed move (locked file, AV interference) leaves the old install in place and recoverable. The updater logs to updater.log in the install dir.
Triggered from Settings → Maintenance → Uninstall WKVRCProxy (with confirm dialog). The UI sends LAUNCH_UNINSTALLER, spawns uninstall.exe, and exits.
- Native confirm dialog (WinForms): explains exactly what gets deleted.
- Closes WKVRCProxy gracefully (
CloseMainWindowthen force-kill after 5 s). - Polls the single-instance mutex (10 s timeout).
- Reads
customVrcPathfromsettings.jsonif present and valid; else usesVrcPathLocator.Find(null). - Calls
PatcherService.RestoreYtDlpInTools()to revert VRChat'syt-dlp.exefromyt-dlp-og.exe. - Deletes
%LOCALAPPDATA%\WKVRCProxy\. - Schedules install dir delete via
cmd.exe /c timeout 2 && rmdir /s /q "<install>"(delayed souninstall.exeitself isn't holding any of those files). - Shows a success dialog, exits.
What it does not touch:
- The hosts file entry
127.0.0.1 localhost.youtube.com. Idle and harmless; users can remove it by hand. -
app_config.jsonandstrategy_memory.json— they live next to the exe and go with the install dir delete.
-
Hardcoded GitHub URL: both
AppUpdateCheckerand the updater hitapi.github.com/repos/RealWhyKnot/WKVRCProxy. If the repo moves, all installs need a manual update. -
Protected install location: if WKVRCProxy is installed in
Program Files, the deferredcmd.exe rmdirruns without elevation and may silently fail. Document install-anywhere usage in the README. -
No SHA256 in release notes: the updater refuses to proceed (exit code 12).
release.ymlalways emitsSHA256: <hex>fromGet-FileHash, so this only happens if a release is published by another path. Add the line manually to the release body and the next update attempt will succeed. -
Zip with path-traversal entries: the updater rejects the whole update (exit code 13) rather than extracting a partial payload. Should never trip on a
release.yml-produced zip; if it does, treat as a tampering signal. -
Updater + UI version mismatch: the updater binary lives next to the UI, so they bump together. If a user manually replaces
updater.exefrom a different release, behaviour is undefined.
Start here
For users
Reference
For maintainers