#Requires -RunAsAdministrator <# .SYNOPSIS Removes the mbproxy Windows Service and its installed files. .DESCRIPTION Stops the service, deletes the service registration, removes the binary install directory, and (unless -KeepConfig is specified) removes the data directory. Log files are always preserved: they are moved to a timestamped archive directory so post-uninstall diagnostics remain accessible. .PARAMETER ServiceName Windows Service name to uninstall. Default: mbproxy .PARAMETER InstallPath Directory that was used as the install target. Default: C:\Program Files\Mbproxy .PARAMETER KeepConfig If specified, leaves %ProgramData%\mbproxy\appsettings.json in place. Logs are always preserved regardless of this flag. .EXAMPLE .\uninstall.ps1 .EXAMPLE .\uninstall.ps1 -KeepConfig #> [CmdletBinding()] param( [string]$ServiceName = 'mbproxy', [string]$InstallPath = 'C:\Program Files\Mbproxy', [switch]$KeepConfig ) Set-StrictMode -Version Latest $ErrorActionPreference = 'Stop' Write-Host "Uninstalling mbproxy service..." -ForegroundColor Cyan Write-Host " ServiceName : $ServiceName" Write-Host " InstallPath : $InstallPath" Write-Host " KeepConfig : $KeepConfig" # ── 1. Stop the service ─────────────────────────────────────────────────────────────────── $svc = Get-Service -Name $ServiceName -ErrorAction SilentlyContinue if ($svc) { if ($svc.Status -eq 'Running') { Write-Host "Stopping service '$ServiceName'..." sc.exe stop $ServiceName | Out-Null $deadline = [DateTime]::UtcNow.AddSeconds(30) do { Start-Sleep -Milliseconds 500 $svc = Get-Service -Name $ServiceName -ErrorAction SilentlyContinue } while ($svc -and $svc.Status -ne 'Stopped' -and [DateTime]::UtcNow -lt $deadline) $svc = Get-Service -Name $ServiceName -ErrorAction SilentlyContinue if ($svc -and $svc.Status -ne 'Stopped') { Write-Warning "Service did not stop within 30 s — attempting force delete." } } # ── 2. Delete the service ───────────────────────────────────────────────────────────── Write-Host "Deleting service registration '$ServiceName'..." sc.exe delete $ServiceName | Out-Null if ($LASTEXITCODE -ne 0) { Write-Warning "sc.exe delete returned $LASTEXITCODE — the service entry may already be gone." } } else { Write-Host "Service '$ServiceName' not found — skipping stop/delete." } # ── 3. Archive log files ───────────────────────────────────────────────────────────────── # Logs are ALWAYS archived (never deleted) so post-uninstall crash diagnostics survive. $dataDir = Join-Path $env:ProgramData 'mbproxy' $logDir = Join-Path $dataDir 'logs' if (Test-Path $logDir) { $timestamp = [DateTime]::UtcNow.ToString('yyyyMMddTHHmmssZ') $archiveName = "mbproxy.archived-$timestamp" $archiveRoot = Join-Path $env:ProgramData $archiveName $archiveLogs = Join-Path $archiveRoot 'logs' Write-Host "Archiving logs to '$archiveLogs'..." New-Item -ItemType Directory -Force $archiveLogs | Out-Null Get-ChildItem -Path $logDir | ForEach-Object { Move-Item -Path $_.FullName -Destination $archiveLogs -Force } Write-Host " Logs archived to: $archiveLogs" -ForegroundColor Yellow } # ── 4. Remove data directory ───────────────────────────────────────────────────────────── if (Test-Path $dataDir) { if ($KeepConfig) { # Remove everything except appsettings.json; then remove the now-empty log dir. Write-Host "Keeping config at '$dataDir\appsettings.json' (-KeepConfig specified)." $logDirPath = Join-Path $dataDir 'logs' if (Test-Path $logDirPath) { Remove-Item -Recurse -Force $logDirPath -ErrorAction SilentlyContinue } } else { Write-Host "Removing data directory '$dataDir'..." Remove-Item -Recurse -Force $dataDir -ErrorAction SilentlyContinue } } # ── 5. Remove binary install directory ─────────────────────────────────────────────────── if (Test-Path $InstallPath) { Write-Host "Removing install directory '$InstallPath'..." Remove-Item -Recurse -Force $InstallPath -ErrorAction SilentlyContinue } else { Write-Host "Install directory '$InstallPath' not found — skipping." } # ── 6. Remove Windows Event Log source ─────────────────────────────────────────────────── if ([System.Diagnostics.EventLog]::SourceExists('mbproxy')) { Write-Host "Removing Windows Event Log source 'mbproxy'..." try { # .NET API, not Remove-EventLog: the *-EventLog cmdlets exist only in # Windows PowerShell 5.1, not PowerShell 7+. Symmetric with the # SourceExists check above. [System.Diagnostics.EventLog]::DeleteEventSource('mbproxy') } catch { Write-Warning "Could not remove Event Log source: $_" } } else { Write-Host "Windows Event Log source 'mbproxy' not registered — skipping." } Write-Host "" Write-Host "Uninstall complete." -ForegroundColor Green if (Test-Path (Join-Path $env:ProgramData 'mbproxy.archived-*')) { Write-Host "Archived logs can be found under: $env:ProgramData\mbproxy.archived-*" -ForegroundColor Yellow }