mirror of
https://github.com/KRTirtho/spotube.git
synced 2026-05-06 15:24:36 +00:00
feat(windows): add GUI uninstaller script
Adds a Windows-specific uninstaller under windows/uninstaller/ that: - Shows a Yes/No confirmation dialog via Windows Forms - Displays a live progress window (no console) during removal - Removes app files, Start Menu/Desktop/Startup shortcuts, AppData configuration, and all registry entries - Mirrors paths/keys from the Inno Setup installer (inno_setup.iss) - Includes a Register-SpotubeUninstaller.ps1 helper to surface the uninstaller in Control Panel -> Programs and Features - Provides a .bat wrapper (WindowStyle Hidden) so only GUI dialogs show Closes: N/A
This commit is contained in:
parent
2cc8d2620d
commit
4b09d2133d
85
windows/uninstaller/Register-SpotubeUninstaller.ps1
Normal file
85
windows/uninstaller/Register-SpotubeUninstaller.ps1
Normal file
@ -0,0 +1,85 @@
|
|||||||
|
<#
|
||||||
|
.SYNOPSIS
|
||||||
|
Registers the Spotube custom uninstaller in Windows Programs and Features.
|
||||||
|
.DESCRIPTION
|
||||||
|
Writes a registry entry to HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall
|
||||||
|
so that Spotube appears in Control Panel -> Programs and Features and in
|
||||||
|
Settings -> Apps -> Installed Apps. The UninstallString points to Uninstall-Spotube.bat
|
||||||
|
which must be in the same directory as this script.
|
||||||
|
.NOTES
|
||||||
|
Requires: Uninstall-Spotube.bat in the same folder.
|
||||||
|
Run as Administrator.
|
||||||
|
#>
|
||||||
|
param()
|
||||||
|
|
||||||
|
# Re-elevate if not already running as Administrator.
|
||||||
|
$isAdmin = ([Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole(
|
||||||
|
[Security.Principal.WindowsBuiltInRole]::Administrator
|
||||||
|
)
|
||||||
|
if (-not $isAdmin) {
|
||||||
|
Start-Process powershell -ArgumentList "-NoProfile -ExecutionPolicy Bypass -File `"$PSCommandPath`"" -Verb RunAs
|
||||||
|
exit
|
||||||
|
}
|
||||||
|
|
||||||
|
$scriptDir = Split-Path -Parent $PSCommandPath
|
||||||
|
$uninstallBat = Join-Path $scriptDir "Uninstall-Spotube.bat"
|
||||||
|
|
||||||
|
if (-Not (Test-Path $uninstallBat)) {
|
||||||
|
Write-Error "Uninstall-Spotube.bat not found in '$scriptDir'. Ensure all uninstaller files are kept together."
|
||||||
|
pause
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
# Version sourced from pubspec.yaml (5.1.1+44). Override if the installed exe exposes a FileVersion.
|
||||||
|
$displayVersion = "5.1.1"
|
||||||
|
$iconPath = ""
|
||||||
|
|
||||||
|
foreach ($candidate in @(
|
||||||
|
(Join-Path $env:ProgramFiles "Spotube\spotube.exe"),
|
||||||
|
(Join-Path $env:LOCALAPPDATA "Programs\Spotube\spotube.exe")
|
||||||
|
)) {
|
||||||
|
if (Test-Path $candidate) {
|
||||||
|
$fileVer = (Get-Item $candidate).VersionInfo.FileVersion
|
||||||
|
if ($fileVer) { $displayVersion = $fileVer }
|
||||||
|
$iconPath = $candidate
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$regPath = "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\SpotubeCustomUninstaller"
|
||||||
|
|
||||||
|
if (-Not (Test-Path $regPath)) {
|
||||||
|
New-Item -Path $regPath -Force | Out-Null
|
||||||
|
}
|
||||||
|
|
||||||
|
# Registry values follow the standard Windows "Add/Remove Programs" schema.
|
||||||
|
$stringValues = @{
|
||||||
|
DisplayName = "Spotube"
|
||||||
|
DisplayVersion = $displayVersion
|
||||||
|
Publisher = "KRTirtho, OSS"
|
||||||
|
URLInfoAbout = "https://github.com/KRTirtho/spotube"
|
||||||
|
HelpLink = "https://github.com/KRTirtho/spotube/issues"
|
||||||
|
UninstallString = "`"$uninstallBat`""
|
||||||
|
InstallDate = (Get-Date -Format "yyyyMMdd")
|
||||||
|
}
|
||||||
|
$dwordValues = @{
|
||||||
|
NoModify = 1
|
||||||
|
NoRepair = 1
|
||||||
|
EstimatedSize = 80000 # Approximate installed size in KB
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach ($kv in $stringValues.GetEnumerator()) {
|
||||||
|
Set-ItemProperty -Path $regPath -Name $kv.Key -Value $kv.Value
|
||||||
|
}
|
||||||
|
foreach ($kv in $dwordValues.GetEnumerator()) {
|
||||||
|
Set-ItemProperty -Path $regPath -Name $kv.Key -Value $kv.Value -Type DWord
|
||||||
|
}
|
||||||
|
if ($iconPath) {
|
||||||
|
Set-ItemProperty -Path $regPath -Name "DisplayIcon" -Value "$iconPath,0"
|
||||||
|
}
|
||||||
|
|
||||||
|
Write-Host ""
|
||||||
|
Write-Host "Spotube registered in Programs and Features." -ForegroundColor Green
|
||||||
|
Write-Host "Open Control Panel -> Programs and Features (or Settings -> Apps) to uninstall."
|
||||||
|
Write-Host ""
|
||||||
|
pause
|
||||||
4
windows/uninstaller/Uninstall-Spotube.bat
Normal file
4
windows/uninstaller/Uninstall-Spotube.bat
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
@echo off
|
||||||
|
:: Launches the Spotube GUI uninstaller without showing a console window.
|
||||||
|
:: -WindowStyle Hidden ensures only the WinForms dialogs are visible.
|
||||||
|
powershell -NoProfile -ExecutionPolicy Bypass -WindowStyle Hidden -File "%~dp0Uninstall-Spotube.ps1"
|
||||||
203
windows/uninstaller/Uninstall-Spotube.ps1
Normal file
203
windows/uninstaller/Uninstall-Spotube.ps1
Normal file
@ -0,0 +1,203 @@
|
|||||||
|
<#
|
||||||
|
.SYNOPSIS
|
||||||
|
GUI-based uninstaller for Spotube on Windows.
|
||||||
|
.DESCRIPTION
|
||||||
|
Removes all Spotube installation artifacts: application files, shortcuts,
|
||||||
|
user data, and registry entries. Mirrors what the Inno Setup installer
|
||||||
|
creates (inno_setup.iss / make_config.yaml).
|
||||||
|
.PARAMETER Silent
|
||||||
|
Suppresses all GUI dialogs and runs non-interactively.
|
||||||
|
#>
|
||||||
|
param (
|
||||||
|
[switch]$Silent
|
||||||
|
)
|
||||||
|
|
||||||
|
# Application metadata — must match Inno Setup make_config.yaml
|
||||||
|
$APP_NAME = "Spotube"
|
||||||
|
$APP_ID = "80B901C8-D6FE-494E-8AF7-A2BD440E8644"
|
||||||
|
$INNO_REG_KEY = "${APP_ID}_is1"
|
||||||
|
$CUSTOM_REG_KEY = "SpotubeCustomUninstaller"
|
||||||
|
|
||||||
|
Add-Type -AssemblyName System.Windows.Forms
|
||||||
|
Add-Type -AssemblyName System.Drawing
|
||||||
|
|
||||||
|
# Displays a standard Windows message box and returns the DialogResult.
|
||||||
|
function Show-MessageBox {
|
||||||
|
param(
|
||||||
|
[string]$Message,
|
||||||
|
[string]$Title = "Spotube Uninstaller",
|
||||||
|
[System.Windows.Forms.MessageBoxButtons]$Buttons = [System.Windows.Forms.MessageBoxButtons]::OK,
|
||||||
|
[System.Windows.Forms.MessageBoxIcon]$Icon = [System.Windows.Forms.MessageBoxIcon]::Information
|
||||||
|
)
|
||||||
|
return [System.Windows.Forms.MessageBox]::Show($Message, $Title, $Buttons, $Icon)
|
||||||
|
}
|
||||||
|
|
||||||
|
# Creates and displays the progress window. Returns a hashtable of controls
|
||||||
|
# so the caller can update label text, sub-label, and progress bar value.
|
||||||
|
function Show-ProgressForm {
|
||||||
|
$form = New-Object System.Windows.Forms.Form
|
||||||
|
$form.Text = "Spotube Uninstaller"
|
||||||
|
$form.Size = New-Object System.Drawing.Size(460, 200)
|
||||||
|
$form.StartPosition = "CenterScreen"
|
||||||
|
$form.FormBorderStyle = "FixedDialog"
|
||||||
|
$form.MaximizeBox = $false
|
||||||
|
$form.MinimizeBox = $false
|
||||||
|
$form.ControlBox = $false # Disable X button during active uninstall
|
||||||
|
$form.TopMost = $true
|
||||||
|
|
||||||
|
# Use the installed Spotube executable's icon if available
|
||||||
|
foreach ($candidate in @(
|
||||||
|
(Join-Path $env:ProgramFiles "Spotube\spotube.exe"),
|
||||||
|
(Join-Path $env:LOCALAPPDATA "Programs\Spotube\spotube.exe")
|
||||||
|
)) {
|
||||||
|
if (Test-Path $candidate) {
|
||||||
|
try { $form.Icon = [System.Drawing.Icon]::ExtractAssociatedIcon($candidate) } catch {}
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$lblStatus = New-Object System.Windows.Forms.Label
|
||||||
|
$lblStatus.Location = New-Object System.Drawing.Point(16, 16)
|
||||||
|
$lblStatus.Size = New-Object System.Drawing.Size(420, 20)
|
||||||
|
$lblStatus.Text = "Preparing..."
|
||||||
|
$lblStatus.Font = New-Object System.Drawing.Font("Segoe UI", 10)
|
||||||
|
$form.Controls.Add($lblStatus)
|
||||||
|
|
||||||
|
$progressBar = New-Object System.Windows.Forms.ProgressBar
|
||||||
|
$progressBar.Location = New-Object System.Drawing.Point(16, 48)
|
||||||
|
$progressBar.Size = New-Object System.Drawing.Size(420, 22)
|
||||||
|
$progressBar.Minimum = 0
|
||||||
|
$progressBar.Maximum = 100
|
||||||
|
$progressBar.Value = 0
|
||||||
|
$form.Controls.Add($progressBar)
|
||||||
|
|
||||||
|
$lblDetail = New-Object System.Windows.Forms.Label
|
||||||
|
$lblDetail.Location = New-Object System.Drawing.Point(16, 80)
|
||||||
|
$lblDetail.Size = New-Object System.Drawing.Size(420, 16)
|
||||||
|
$lblDetail.Text = ""
|
||||||
|
$lblDetail.Font = New-Object System.Drawing.Font("Segoe UI", 8)
|
||||||
|
$lblDetail.ForeColor = [System.Drawing.Color]::DimGray
|
||||||
|
$form.Controls.Add($lblDetail)
|
||||||
|
|
||||||
|
$form.Show()
|
||||||
|
$form.Refresh()
|
||||||
|
|
||||||
|
return @{
|
||||||
|
Form = $form
|
||||||
|
Status = $lblStatus
|
||||||
|
Detail = $lblDetail
|
||||||
|
Progress = $progressBar
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# Re-elevate as Administrator if the script is not already running elevated.
|
||||||
|
$isAdmin = ([Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole(
|
||||||
|
[Security.Principal.WindowsBuiltInRole]::Administrator
|
||||||
|
)
|
||||||
|
if (-not $isAdmin) {
|
||||||
|
$relaunchArgs = "-NoProfile -ExecutionPolicy Bypass -File `"$PSCommandPath`""
|
||||||
|
if ($Silent) { $relaunchArgs += " -Silent" }
|
||||||
|
Start-Process powershell -ArgumentList $relaunchArgs -Verb RunAs
|
||||||
|
exit
|
||||||
|
}
|
||||||
|
|
||||||
|
# Prompt the user before making any changes.
|
||||||
|
if (-not $Silent) {
|
||||||
|
$confirmMsg = @"
|
||||||
|
Are you sure you want to uninstall Spotube?
|
||||||
|
|
||||||
|
This will permanently remove:
|
||||||
|
• Application files
|
||||||
|
• Desktop, Start Menu, and Startup shortcuts
|
||||||
|
• User configuration and cached data
|
||||||
|
• Windows registry entries
|
||||||
|
"@
|
||||||
|
$result = Show-MessageBox -Message $confirmMsg -Title "Uninstall Spotube" `
|
||||||
|
-Buttons ([System.Windows.Forms.MessageBoxButtons]::YesNo) `
|
||||||
|
-Icon ([System.Windows.Forms.MessageBoxIcon]::Question)
|
||||||
|
|
||||||
|
if ($result -ne [System.Windows.Forms.DialogResult]::Yes) {
|
||||||
|
Show-MessageBox -Message "Uninstallation was cancelled. No changes were made." `
|
||||||
|
-Title "Cancelled" -Icon ([System.Windows.Forms.MessageBoxIcon]::Information)
|
||||||
|
exit
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$ui = Show-ProgressForm
|
||||||
|
|
||||||
|
# Updates the progress window with new status text and a percentage value.
|
||||||
|
function Update-Progress ([string]$status, [string]$detail, [int]$percent) {
|
||||||
|
$ui.Status.Text = $status
|
||||||
|
$ui.Detail.Text = $detail
|
||||||
|
$ui.Progress.Value = [Math]::Min($percent, 100)
|
||||||
|
$ui.Form.Refresh()
|
||||||
|
}
|
||||||
|
|
||||||
|
# Silently removes a file or directory; no-ops if the path does not exist.
|
||||||
|
function Safe-Remove ([string]$path) {
|
||||||
|
if ($path -and (Test-Path $path)) {
|
||||||
|
try { Remove-Item -Path $path -Recurse -Force -ErrorAction Stop } catch {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# Step 1: Terminate any running Spotube processes before touching files.
|
||||||
|
Update-Progress "Stopping Spotube..." "Terminating running processes" 5
|
||||||
|
Get-Process -Name "spotube" -ErrorAction SilentlyContinue |
|
||||||
|
Stop-Process -Force -ErrorAction SilentlyContinue
|
||||||
|
Start-Sleep -Milliseconds 1500
|
||||||
|
|
||||||
|
# Step 2: Delete the installation directory.
|
||||||
|
# Inno Setup installs to {autopf}\Spotube — covers both admin and per-user installs.
|
||||||
|
Update-Progress "Removing application files..." "Deleting installation directory" 20
|
||||||
|
@(
|
||||||
|
(Join-Path $env:ProgramFiles $APP_NAME),
|
||||||
|
(Join-Path $env:ProgramW6432 $APP_NAME),
|
||||||
|
(Join-Path $env:LOCALAPPDATA "Programs\$APP_NAME")
|
||||||
|
) | Select-Object -Unique | ForEach-Object { Safe-Remove $_ }
|
||||||
|
|
||||||
|
# Step 3: Remove shortcuts created by the Inno Setup [Icons] section.
|
||||||
|
# Covers: {autoprograms} (Start Menu), {autodesktop} (Desktop), {userstartup} (Startup).
|
||||||
|
Update-Progress "Removing shortcuts..." "Cleaning Start Menu, Desktop, and Startup" 40
|
||||||
|
@(
|
||||||
|
(Join-Path $env:ProgramData "Microsoft\Windows\Start Menu\Programs\$APP_NAME.lnk"),
|
||||||
|
(Join-Path $env:APPDATA "Microsoft\Windows\Start Menu\Programs\$APP_NAME.lnk"),
|
||||||
|
(Join-Path $env:ProgramData "Microsoft\Windows\Start Menu\Programs\$APP_NAME"),
|
||||||
|
(Join-Path $env:APPDATA "Microsoft\Windows\Start Menu\Programs\$APP_NAME"),
|
||||||
|
(Join-Path ([Environment]::GetFolderPath("CommonDesktopDirectory")) "$APP_NAME.lnk"),
|
||||||
|
(Join-Path ([Environment]::GetFolderPath("Desktop")) "$APP_NAME.lnk"),
|
||||||
|
(Join-Path $env:APPDATA "Microsoft\Windows\Start Menu\Programs\Startup\$APP_NAME.lnk")
|
||||||
|
) | ForEach-Object { Safe-Remove $_ }
|
||||||
|
|
||||||
|
# Step 4: Remove Flutter application data stored in AppData.
|
||||||
|
Update-Progress "Removing user data..." "Clearing configuration and cache" 60
|
||||||
|
@(
|
||||||
|
(Join-Path $env:APPDATA "com.krtirtho.spotube"),
|
||||||
|
(Join-Path $env:LOCALAPPDATA "com.krtirtho.spotube"),
|
||||||
|
(Join-Path $env:APPDATA "spotube"),
|
||||||
|
(Join-Path $env:LOCALAPPDATA "spotube")
|
||||||
|
) | ForEach-Object { Safe-Remove $_ }
|
||||||
|
|
||||||
|
# Step 5: Remove all Windows registry entries.
|
||||||
|
# Targets the Inno Setup key ({AppId}_is1) and our custom Control Panel key.
|
||||||
|
Update-Progress "Removing registry entries..." "Cleaning uninstall records" 80
|
||||||
|
foreach ($root in @("HKLM:\SOFTWARE", "HKCU:\SOFTWARE", "HKLM:\SOFTWARE\WOW6432Node")) {
|
||||||
|
foreach ($key in @($INNO_REG_KEY, $CUSTOM_REG_KEY)) {
|
||||||
|
Safe-Remove "$root\Microsoft\Windows\CurrentVersion\Uninstall\$key"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Safe-Remove "HKCU:\SOFTWARE\KRTirtho"
|
||||||
|
Safe-Remove "HKCU:\SOFTWARE\Spotube"
|
||||||
|
|
||||||
|
Update-Progress "Complete" "Spotube has been removed." 100
|
||||||
|
Start-Sleep -Milliseconds 500
|
||||||
|
$ui.Form.Close()
|
||||||
|
$ui.Form.Dispose()
|
||||||
|
|
||||||
|
# Show the final confirmation dialog with an OK button to dismiss.
|
||||||
|
if (-not $Silent) {
|
||||||
|
Show-MessageBox `
|
||||||
|
-Message "Spotube has been successfully uninstalled.`n`nClick OK to close." `
|
||||||
|
-Title "Uninstall Complete" `
|
||||||
|
-Buttons ([System.Windows.Forms.MessageBoxButtons]::OK) `
|
||||||
|
-Icon ([System.Windows.Forms.MessageBoxIcon]::Information)
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue
Block a user