Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
77 changes: 77 additions & 0 deletions scripts/install-service.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -543,6 +543,46 @@ if ($FromZip) {
throw "This zip is not self-contained (no hostfxr.dll), so it would need a .NET runtime on this host. Refusing to install it."
}

# ⛔ Preserve host-local configuration BEFORE the wipe below.
#
# That wipe deletes everything in the install directory, so an upgrade used to destroy
# appsettings.json AND appsettings.local.json and then drop the shipped defaults in their
# place. Nothing was backed up and nothing said so. The API survived only by accident,
# because ResolveApiKey falls back to a file in ProgramData that this never touches;
# every setting without such a fallback was simply gone. See issue #45.
#
# ⚠️ appsettings.local.json is the documented place for host-local settings precisely
# because a deploy cannot overwrite it — true of `dotnet publish`, and NOT true here
# until now. Read that advice as conditional on this block existing.
# ⭐ Preserve the FILES, byte for byte — never their text.
#
# Round-tripping through Get-Content/Set-Content rewrites the file: Set-Content appends a
# trailing newline and can change the encoding, so a "preserved" file came back two bytes
# different from the one the user wrote. Harmless for JSON today, wrong in principle for a
# step whose entire job is to leave the user's file alone, and a trap the moment anything
# here is not JSON.
$preserveNames = @('appsettings.json', 'appsettings.local.json')
$preserved = @{}
$backupDir = $null
foreach ($name in $preserveNames) {
$existing = Join-Path $InstallDir $name
if (Test-Path $existing) {
if (-not $backupDir) {
$backupDir = Join-Path $env:ProgramData ("MultiSeat\config-backups\" + (Get-Date -Format 'yyyyMMdd-HHmmss'))
New-Item -ItemType Directory -Path $backupDir -Force | Out-Null
}
# The backup doubles as the staging copy: one byte-exact copy, used for both.
# It lives outside the install directory because the wipe below is the very thing
# being protected against.
$kept = Join-Path $backupDir $name
Copy-Item $existing $kept -Force
$preserved[$name] = $kept
}
}
if ($preserved.Count -gt 0) {
Write-Host " Backed up $($preserved.Count) config file(s) to $backupDir" -ForegroundColor DarkGray
}

if (Test-Path $InstallDir) {
Get-ChildItem $InstallDir -Force | Remove-Item -Recurse -Force -ErrorAction SilentlyContinue
} else {
Expand All @@ -558,6 +598,43 @@ if ($FromZip) {
Where-Object { $skip -notcontains $_.Name } |
ForEach-Object { Copy-Item $_.FullName $InstallDir -Recurse -Force }

# -- Put host configuration back over the shipped defaults --------------
#
# An upgrade must not silently change how this host is configured. The shipped
# appsettings.json is what a FIRST install needs; on an upgrade the host's own copy wins.
if ($preserved.ContainsKey('appsettings.local.json')) {
Copy-Item $preserved['appsettings.local.json'] `
(Join-Path $InstallDir 'appsettings.local.json') -Force
Write-Host " Restored appsettings.local.json" -ForegroundColor DarkGray
}

if ($preserved.ContainsKey('appsettings.json')) {
$shippedPath = Join-Path $InstallDir 'appsettings.json'

# Report settings this release added that the host's file does not carry. Keeping the
# host's file is right, but doing it silently would hide a new option forever — the
# one real cost of preserving over replacing, so it is surfaced rather than ignored.
try {
$shippedKeys = ((Get-Content $shippedPath -Raw | ConvertFrom-Json).MultiSeat |
Get-Member -MemberType NoteProperty).Name
$hostKeys = ((Get-Content $preserved['appsettings.json'] -Raw | ConvertFrom-Json).MultiSeat |
Get-Member -MemberType NoteProperty).Name
$newKeys = @($shippedKeys | Where-Object { $hostKeys -notcontains $_ })
if ($newKeys.Count -gt 0) {
Write-Host ""
Write-Host " This release adds $($newKeys.Count) setting(s) your appsettings.json does not have:" -ForegroundColor Yellow
$newKeys | ForEach-Object { Write-Host " MultiSeat:$_" -ForegroundColor Yellow }
Write-Host " Your file was kept as-is, so these run at their built-in defaults." -ForegroundColor Yellow
Write-Host ""
}
} catch {
Write-Host " NOTE: could not compare settings against the shipped file ($_)" -ForegroundColor Yellow
}

Copy-Item $preserved['appsettings.json'] $shippedPath -Force
Write-Host " Kept your existing appsettings.json (shipped defaults not applied)" -ForegroundColor DarkGray
}

$ver = "unknown"
try {
$ver = (& "$InstallDir\MultiSeat.Service.exe" --config 2>&1 |
Expand Down
Loading