Files
UnheardCity/tools/installer/install.ps1
2026-10-09 02:48:24 +02:00

80 lines
4.1 KiB
PowerShell

# Unheard City - per-user installer (no admin rights needed). Run "Install.cmd" next to this file.
# install.ps1 [-Target DIR] [-Desktop yes|no] [-Quiet]
# Copies the app to %LOCALAPPDATA%\Programs\UnheardCity, adds a Start menu (and optionally desktop) shortcut and
# an "Unheard City" entry in Settings > Apps for uninstalling. Running it again upgrades in place.
param(
[string]$Target = (Join-Path $env:LOCALAPPDATA "Programs\UnheardCity"),
[ValidateSet("ask", "yes", "no")][string]$Desktop = "ask",
[switch]$Quiet
)
$ErrorActionPreference = "Stop"
$Name = "Unheard City"
$Exe = "UnheardCity.exe"
$Version = "@VERSION@"
$Src = $PSScriptRoot
$RegKey = "HKCU:\Software\Microsoft\Windows\CurrentVersion\Uninstall\UnheardCity"
$StartLnk = Join-Path ([Environment]::GetFolderPath("Programs")) "$Name.lnk"
$DesktopLnk = Join-Path ([Environment]::GetFolderPath("Desktop")) "$Name.lnk"
function Say($msg) { if (-not $Quiet) { Write-Host $msg } }
function Shortcut($path, $target, $workdir) {
$s = (New-Object -ComObject WScript.Shell).CreateShortcut($path)
$s.TargetPath = $target
$s.WorkingDirectory = $workdir
$s.IconLocation = "$target,0"
$s.Description = "Replace voice lines, music and ambience in Batman: Arkham City"
$s.Save()
}
try {
if (-not (Test-Path (Join-Path $Src $Exe))) { throw "$Exe not found next to this script. Unzip the whole download first." }
$Target = [IO.Path]::GetFullPath($Target)
if ([IO.Path]::GetFullPath($Src).TrimEnd('\') -ieq $Target.TrimEnd('\')) { throw "This copy is already the installed one." }
$running = Get-Process -Name "UnheardCity" -ErrorAction SilentlyContinue | Where-Object { $_.Path -and $_.Path.StartsWith($Target, [StringComparison]::OrdinalIgnoreCase) }
if ($running) { throw "$Name is running. Close it and run the installer again." }
Say "Installing $Name $Version to $Target ..."
if (Test-Path $Target) {
# upgrade: replace the program files only (user data lives in %APPDATA%\UnheardCity, not here)
$isOurs = (Test-Path (Join-Path $Target $Exe)) -or -not (Get-ChildItem -LiteralPath $Target -Force)
if (-not $isOurs) { throw "$Target exists and is not an $Name installation; choose another folder." }
Get-ChildItem -LiteralPath $Target -Force | Remove-Item -Recurse -Force
} else {
New-Item -ItemType Directory -Path $Target | Out-Null
}
Get-ChildItem -LiteralPath $Src -Force | Where-Object { $_.Name -notin @("Install.cmd", "install.ps1") } |
Copy-Item -Destination $Target -Recurse -Force
$exePath = Join-Path $Target $Exe
Shortcut $StartLnk $exePath $Target
$wantDesktop = $Desktop -eq "yes"
if ($Desktop -eq "ask" -and -not $Quiet) {
$wantDesktop = (Read-Host "Add a desktop shortcut? [Y/n]") -notmatch '^(n|no)$'
}
if ($wantDesktop) { Shortcut $DesktopLnk $exePath $Target }
$kb = [int]((Get-ChildItem -LiteralPath $Target -Recurse -File | Measure-Object Length -Sum).Sum / 1KB)
$uninst = Join-Path $Target "uninstall.ps1"
New-Item -Path $RegKey -Force | Out-Null
$props = @{
DisplayName = $Name; DisplayVersion = $Version; Publisher = "Unheard City"; DisplayIcon = "$exePath,0"
InstallLocation = $Target; EstimatedSize = $kb; NoModify = 1; NoRepair = 1
UninstallString = "powershell.exe -NoProfile -ExecutionPolicy Bypass -File `"$uninst`""
QuietUninstallString = "powershell.exe -NoProfile -ExecutionPolicy Bypass -File `"$uninst`" -Quiet"
}
foreach ($k in $props.Keys) {
$type = if ($props[$k] -is [int]) { "DWord" } else { "String" }
New-ItemProperty -Path $RegKey -Name $k -Value $props[$k] -PropertyType $type -Force | Out-Null
}
Say ""
Say "$Name is installed. Start it from the Start menu$(if ($wantDesktop) { ' or the desktop' })."
Say "Uninstall: Settings > Apps > Installed apps > $Name."
if (-not $Quiet -and (Read-Host "Start $Name now? [Y/n]") -notmatch '^(n|no)$') { Start-Process $exePath -WorkingDirectory $Target }
exit 0
} catch {
Write-Host ""
Write-Host "Installation failed: $($_.Exception.Message)" -ForegroundColor Red
exit 1
}