diff --git a/deploy/README-DEPLOY.txt b/deploy/README-DEPLOY.txt index 8a02482..b2849c8 100644 --- a/deploy/README-DEPLOY.txt +++ b/deploy/README-DEPLOY.txt @@ -9,12 +9,15 @@ NO reboot. Contents -------- postinstall.bat Entry point (at the root). Elevates, then runs - riojoy\install-rio.ps1. - riojoy\ The payload folder: + RIOJoy\install-rio.ps1. + RIOJoy\ The payload folder: app\ The RIOJoy tray application (self-contained .NET 8 — no runtime install required on the target machine). vendor\ The signed ViGEmBus installer (Nefarius, WHQL/attestation-signed). install-rio.ps1 The actual install steps (idempotent). + pre-uninstall.bat Cleanup entry point. Elevates, then runs uninstall-rio.ps1. + Run this before deleting the RIOJoy folder. + uninstall-rio.ps1 The actual cleanup steps (idempotent). VERSION.txt Build stamp (date + git short SHA). What postinstall.bat does @@ -26,12 +29,21 @@ What postinstall.bat does Deploying with TeslaConsole --------------------------- - 1. Extract this zip so that postinstall.bat and the riojoy\ folder sit together - (e.g. under C:\games\, giving C:\games\postinstall.bat and C:\games\riojoy\). + 1. Extract this zip so that postinstall.bat and the RIOJoy\ folder sit together + (e.g. under C:\games\, giving C:\games\postinstall.bat and C:\games\RIOJoy\). 2. Run postinstall.bat ELEVATED (TeslaConsole should run it as administrator). It is idempotent — re-running it is safe (e.g. for updates). The app and - ViGEmBus install from the riojoy\ folder; install-rio.ps1 locates itself, so - the riojoy\ folder can live wherever it is extracted. + ViGEmBus install from the RIOJoy\ folder; install-rio.ps1 locates itself, so + the RIOJoy\ folder can live wherever it is extracted. + +Uninstalling with TeslaConsole +------------------------------ + Before deleting the RIOJoy folder, run RIOJoy\pre-uninstall.bat ELEVATED. It + stops the tray app (releasing file locks), removes the logon entry, uninstalls + ViGEmBus, and clears per-user config (%APPDATA%\RIOJoy) for every profile. It is + idempotent and non-fatal — safe even if RIOJoy was never fully installed. The + console can then delete the folder cleanly. Use -KeepDriver to leave ViGEmBus in + place, or -KeepConfig to leave per-user config. After install ------------- diff --git a/deploy/build-package.ps1 b/deploy/build-package.ps1 index 9cad919..a716aed 100644 --- a/deploy/build-package.ps1 +++ b/deploy/build-package.ps1 @@ -42,9 +42,9 @@ if ($sig.Status -ne 'Valid') { throw "ViGEmBus installer is not validly signed ( Write-Host "ViGEmBus installer: $(Split-Path $VigemInstaller -Leaf) (signature $($sig.Status))" try { - # The payload lives in a 'riojoy' folder; postinstall.bat sits beside it at the - # zip root (TeslaConsole runs it; it calls riojoy\install-rio.ps1). - $pkgDir = Join-Path $staging 'riojoy' + # The payload lives in a 'RIOJoy' folder; postinstall.bat sits beside it at the + # zip root (TeslaConsole runs it; it calls RIOJoy\install-rio.ps1). + $pkgDir = Join-Path $staging 'RIOJoy' New-Item -ItemType Directory -Force -Path $pkgDir | Out-Null # 1. Publish the tray app into riojoy\app (self-contained win-x64 — no .NET on target). @@ -61,9 +61,12 @@ try { New-Item -ItemType Directory -Force -Path $vendorOut | Out-Null Copy-Item $VigemInstaller $vendorOut - # 3. Install script + readme + version stamp inside riojoy\; postinstall.bat at root. - Copy-Item (Join-Path $PSScriptRoot 'install-rio.ps1') $pkgDir - Copy-Item (Join-Path $PSScriptRoot 'README-DEPLOY.txt') $pkgDir + # 3. Install/uninstall scripts + readme + version stamp inside RIOJoy\; + # postinstall.bat at root, pre-uninstall.bat inside the payload folder. + Copy-Item (Join-Path $PSScriptRoot 'install-rio.ps1') $pkgDir + Copy-Item (Join-Path $PSScriptRoot 'uninstall-rio.ps1') $pkgDir + Copy-Item (Join-Path $PSScriptRoot 'pre-uninstall.bat') $pkgDir + Copy-Item (Join-Path $PSScriptRoot 'README-DEPLOY.txt') $pkgDir Set-Content -Path (Join-Path $pkgDir 'VERSION.txt') -Value "RIOJoy $version" -Encoding utf8 Copy-Item (Join-Path $PSScriptRoot 'postinstall.bat') $staging diff --git a/deploy/postinstall.bat b/deploy/postinstall.bat index ae4d217..32b9d7f 100644 --- a/deploy/postinstall.bat +++ b/deploy/postinstall.bat @@ -1,8 +1,8 @@ @echo off rem =========================================================================== rem RIOJoy cockpit post-install entry point (run by TeslaConsole). -rem Sits beside the 'riojoy' payload folder; elevates, then runs -rem riojoy\install-rio.ps1. +rem Sits beside the 'RIOJoy' payload folder; elevates, then runs +rem RIOJoy\install-rio.ps1. rem =========================================================================== setlocal title RIOJoy post-install @@ -17,7 +17,7 @@ if %errorlevel% neq 0 ( cd /d "%~dp0" -powershell -NoProfile -ExecutionPolicy Bypass -File "%~dp0riojoy\install-rio.ps1" +powershell -NoProfile -ExecutionPolicy Bypass -File "%~dp0RIOJoy\install-rio.ps1" set RC=%errorlevel% echo. diff --git a/deploy/pre-uninstall.bat b/deploy/pre-uninstall.bat new file mode 100644 index 0000000..8e69bc3 --- /dev/null +++ b/deploy/pre-uninstall.bat @@ -0,0 +1,30 @@ +@echo off +rem =========================================================================== +rem RIOJoy cockpit pre-uninstall entry point (run by the console before it +rem deletes the RIOJoy folder). Lives INSIDE the RIOJoy folder beside +rem uninstall-rio.ps1; elevates, then runs uninstall-rio.ps1 to stop the app, +rem remove the logon entry, uninstall ViGEmBus, and clear per-user config. +rem =========================================================================== +setlocal +title RIOJoy pre-uninstall + +rem --- elevate if we are not already administrator -------------------------- +net session >nul 2>&1 +if %errorlevel% neq 0 ( + echo Requesting administrator privileges... + powershell -NoProfile -Command "Start-Process -FilePath '%~f0' -Verb RunAs" + exit /b 0 +) + +cd /d "%~dp0" + +powershell -NoProfile -ExecutionPolicy Bypass -File "%~dp0uninstall-rio.ps1" +set RC=%errorlevel% + +echo. +if %RC% neq 0 ( + echo pre-uninstall FAILED with exit code %RC%. +) else ( + echo pre-uninstall completed. +) +exit /b %RC% diff --git a/deploy/uninstall-rio.ps1 b/deploy/uninstall-rio.ps1 new file mode 100644 index 0000000..d5c6760 --- /dev/null +++ b/deploy/uninstall-rio.ps1 @@ -0,0 +1,115 @@ +<# +.SYNOPSIS + RIOJoy cockpit pre-uninstall cleanup. Reverses install-rio.ps1: stops the + running tray app, removes the logon entry, optionally uninstalls ViGEmBus, + and clears per-user config. Must run elevated (pre-uninstall.bat elevates + for you). Idempotent — safe to re-run, and safe to run when RIOJoy was never + fully installed. + +.DESCRIPTION + Run from inside the deployed package directory (e.g. C:\games\RIOJoy) BEFORE + the console deletes the folder. Stopping the tray app releases the file locks + on app\RioJoy.Tray.exe so the folder can then be removed cleanly. This script + does NOT delete its own folder — the console does that after this returns. + +.PARAMETER KeepDriver + Leave ViGEmBus installed (default is to uninstall it, since the RIOJoy package + installed it). Use this if other software on the machine relies on ViGEmBus. + +.PARAMETER KeepConfig + Leave per-user config (%APPDATA%\RIOJoy) in place. Default removes it for every + user profile on the machine. +#> +param( + [switch]$KeepDriver, + [switch]$KeepConfig +) + +$ErrorActionPreference = 'Stop' + +$root = $PSScriptRoot +$vendorDir = Join-Path $root 'vendor' +$runValueName = 'RIOJoy' + +# --- guard ---------------------------------------------------------------- +$principal = [Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent() +if (-not $principal.IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)) { + throw 'uninstall-rio.ps1 must run elevated. Run pre-uninstall.bat (it elevates).' +} + +Write-Host '== RIOJoy pre-uninstall cleanup ==' -ForegroundColor Cyan + +# 1. Stop the running tray app (releases locks on app\RioJoy.Tray.exe). +$procs = Get-Process -Name 'RioJoy.Tray' -ErrorAction SilentlyContinue +if ($procs) { + Write-Host "Stopping RIOJoy ($($procs.Count) process(es))..." + $procs | Stop-Process -Force -ErrorAction SilentlyContinue + Start-Sleep -Milliseconds 500 +} else { + Write-Host 'RIOJoy is not running.' +} + +# 2. Remove the logon entry (machine-wide Run key). +$runKey = 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Run' +if (Get-ItemProperty -Path $runKey -Name $runValueName -ErrorAction SilentlyContinue) { + Write-Host 'Removing logon entry...' + Remove-ItemProperty -Path $runKey -Name $runValueName -Force -ErrorAction SilentlyContinue +} else { + Write-Host 'No logon entry present.' +} + +# 3. Uninstall ViGEmBus (best-effort; non-fatal) unless told to keep it. +if ($KeepDriver) { + Write-Host 'Leaving ViGEmBus installed (-KeepDriver).' +} else { + $svc = Get-Service -Name ViGEmBus -ErrorAction SilentlyContinue + if ($svc) { + $installer = Get-ChildItem -Path $vendorDir -Filter 'ViGEmBus*.exe' -ErrorAction SilentlyContinue | + Select-Object -First 1 + if ($installer) { + Write-Host "Uninstalling ViGEmBus ($($installer.Name))..." + try { + $p = Start-Process -FilePath $installer.FullName ` + -ArgumentList '/uninstall', '/quiet', '/norestart' -Wait -PassThru + if ($p.ExitCode -notin 0, 3010) { + Write-Warning "ViGEmBus uninstall returned exit code $($p.ExitCode) (continuing)." + } else { + Write-Host 'ViGEmBus uninstalled.' + } + } catch { + Write-Warning "ViGEmBus uninstall failed (continuing): $($_.Exception.Message)" + } + } else { + Write-Warning "ViGEmBus is installed but its installer is not in $vendorDir — skipping driver removal." + } + } else { + Write-Host 'ViGEmBus is not installed.' + } +} + +# 4. Remove per-user config for every profile (best-effort) unless told to keep it. +if ($KeepConfig) { + Write-Host 'Leaving per-user config (-KeepConfig).' +} else { + $usersRoot = Join-Path $env:SystemDrive 'Users' + $removed = 0 + if (Test-Path $usersRoot) { + foreach ($profile in Get-ChildItem -Path $usersRoot -Directory -ErrorAction SilentlyContinue) { + $cfg = Join-Path $profile.FullName 'AppData\Roaming\RIOJoy' + if (Test-Path $cfg) { + try { + Remove-Item -Path $cfg -Recurse -Force -ErrorAction Stop + $removed++ + } catch { + Write-Warning "Could not remove $cfg (continuing): $($_.Exception.Message)" + } + } + } + } + Write-Host "Removed per-user config from $removed profile(s)." +} + +# --- summary -------------------------------------------------------------- +Write-Host '' +Write-Host 'RIOJoy cleanup complete. The console may now delete the RIOJoy folder.' -ForegroundColor Green +exit 0