<# .SYNOPSIS AZA Desktop - Sauberes Deinstallations- und Reset-Tool .DESCRIPTION Entfernt AZA Desktop sauber vom System, ohne Neustart. Zwei Modi: 1 = Nur App entfernen, Benutzerdaten behalten 2 = Vollstaendig zuruecksetzen (App + Benutzerdaten) .NOTES Fuer Entwicklungs- und Abnahmetests. Keine gefaehrlichen Loeschaktionen ausserhalb des AZA-Kontexts. #> param( [ValidateSet("1","2")] [string]$Modus ) $ErrorActionPreference = "Continue" $Host.UI.RawUI.WindowTitle = "AZA Desktop - Clean Uninstall / Reset" $AZA_APP_ID = "{B7E4C0D2-6B5D-4D39-9D7C-5B0D5E8C2A11}" $AZA_PROCESS_NAME = "aza_desktop" $AZA_DISPLAY_NAME = "AZA Desktop" $AZA_FIREWALL_RULE = "AZA Desktop - Lokale Kommunikation" $AZA_APPDATA_DIR = Join-Path $env:APPDATA "AZA Desktop" $AZA_DOCS_DIR = Join-Path ([Environment]::GetFolderPath("MyDocuments")) "KG_Diktat_Ablage" $INSTALL_DIR_DEFAULT = Join-Path $env:ProgramFiles "AZA Desktop" # --- Hilfsfunktionen ------------------------------------------------ function Write-Step { param([string]$Icon, [string]$Text) Write-Host "" Write-Host " $Icon $Text" -ForegroundColor Cyan } function Write-Ok { param([string]$Text) Write-Host " [OK] $Text" -ForegroundColor Green } function Write-Skip { param([string]$Text) Write-Host " [--] $Text" -ForegroundColor DarkGray } function Write-Warn { param([string]$Text) Write-Host " [!!] $Text" -ForegroundColor Yellow } function Write-Fail { param([string]$Text) Write-Host " [FEHLER] $Text" -ForegroundColor Red } function Write-Banner { Write-Host "" Write-Host " =============================================" -ForegroundColor White Write-Host " AZA Desktop - Clean Uninstall / Reset Tool" -ForegroundColor White Write-Host " =============================================" -ForegroundColor White Write-Host "" } # --- Schritt 1: Modus waehlen --------------------------------------- function Select-Mode { if ($Modus) { return $Modus } Write-Host " Bitte waehlen Sie den Modus:" -ForegroundColor White Write-Host "" Write-Host " [1] Nur App entfernen, Benutzerdaten BEHALTEN" -ForegroundColor Green Write-Host ' (Profil, Transkripte, Briefe, Einstellungen bleiben erhalten)' -ForegroundColor DarkGray Write-Host "" Write-Host " [2] Vollstaendig zuruecksetzen (App + ALLE Benutzerdaten)" -ForegroundColor Yellow Write-Host ' (Alles wird geloescht: Profil, Transkripte, Briefe, Rezepte,' -ForegroundColor DarkGray Write-Host ' Kostenvoranschlaege, Autotext, Signatur, Einstellungen)' -ForegroundColor DarkGray Write-Host "" do { $choice = Read-Host ' Ihre Wahl [1 oder 2]' } while ($choice -ne "1" -and $choice -ne "2") return $choice } # --- Schritt 2: AZA-Prozesse beenden -------------------------------- function Stop-AzaProcesses { Write-Step "1" "AZA-Prozesse pruefen und beenden" $procs = Get-Process -Name $AZA_PROCESS_NAME -ErrorAction SilentlyContinue if (-not $procs) { Write-Ok "Keine laufenden AZA-Prozesse gefunden." return } $count = @($procs).Count Write-Host " $count AZA-Prozess(e) gefunden. Beende..." -ForegroundColor White foreach ($p in $procs) { try { $p.CloseMainWindow() | Out-Null } catch {} } Start-Sleep -Seconds 2 $remaining = Get-Process -Name $AZA_PROCESS_NAME -ErrorAction SilentlyContinue if ($remaining) { Write-Warn "Prozesse reagieren nicht - erzwinge Beenden..." $remaining | Stop-Process -Force -ErrorAction SilentlyContinue Start-Sleep -Seconds 1 } $still = Get-Process -Name $AZA_PROCESS_NAME -ErrorAction SilentlyContinue if ($still) { Write-Fail "Konnte nicht alle AZA-Prozesse beenden. Bitte manuell schliessen." } else { Write-Ok "Alle AZA-Prozesse beendet ($count Stueck)." } } # --- Schritt 3: Inno Setup Uninstaller aufrufen --------------------- function Find-UninstallString { $regPaths = @( "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\$($AZA_APP_ID)_is1", "HKLM:\SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall\$($AZA_APP_ID)_is1", "HKCU:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\$($AZA_APP_ID)_is1" ) foreach ($rp in $regPaths) { if (Test-Path $rp) { $val = (Get-ItemProperty -Path $rp -ErrorAction SilentlyContinue).UninstallString if ($val) { return $val } } } return $null } function Find-InstallLocation { $regPaths = @( "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\$($AZA_APP_ID)_is1", "HKLM:\SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall\$($AZA_APP_ID)_is1", "HKCU:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\$($AZA_APP_ID)_is1" ) foreach ($rp in $regPaths) { if (Test-Path $rp) { $val = (Get-ItemProperty -Path $rp -ErrorAction SilentlyContinue).InstallLocation if ($val) { return $val.TrimEnd('\') } } } if (Test-Path $INSTALL_DIR_DEFAULT) { return $INSTALL_DIR_DEFAULT } return $null } function Invoke-InnoUninstall { Write-Step "2" "AZA Desktop deinstallieren (Inno Setup)" $uninstStr = Find-UninstallString if (-not $uninstStr) { Write-Skip "Kein Inno-Setup-Uninstaller in der Registry gefunden." Write-Host " Versuche manuelle Bereinigung..." -ForegroundColor DarkGray return $false } $uninstExe = $uninstStr -replace '"', '' if (-not (Test-Path $uninstExe)) { Write-Warn "Uninstaller-Datei nicht gefunden: $uninstExe" return $false } Write-Host " Starte Inno-Setup-Deinstallation (silent)..." -ForegroundColor White try { $proc = Start-Process -FilePath $uninstExe -ArgumentList "/VERYSILENT /NORESTART /SUPPRESSMSGBOXES" ` -Wait -PassThru -ErrorAction Stop if ($proc.ExitCode -eq 0) { Write-Ok "Inno-Setup-Deinstallation erfolgreich abgeschlossen." Start-Sleep -Seconds 2 return $true } else { Write-Warn "Uninstaller beendet mit Code $($proc.ExitCode)." return $false } } catch { Write-Fail "Fehler beim Ausfuehren des Uninstallers: $_" return $false } } # --- Schritt 4: Restdateien bereinigen ------------------------------ function Remove-InstallRemnants { Write-Step "3" "Installationsreste bereinigen" $installDir = Find-InstallLocation if (-not $installDir) { $installDir = $INSTALL_DIR_DEFAULT } if (Test-Path $installDir) { Write-Host " Entferne Installationsverzeichnis: $installDir" -ForegroundColor White try { Remove-Item -Path $installDir -Recurse -Force -ErrorAction Stop Write-Ok "Installationsverzeichnis entfernt." } catch { Write-Warn "Einige Dateien konnten nicht entfernt werden (evtl. gesperrt)." Write-Host " $($_.Exception.Message)" -ForegroundColor DarkGray } } else { Write-Ok "Kein Installationsverzeichnis vorhanden." } $startMenuDir = Join-Path $env:ProgramData 'Microsoft\Windows\Start Menu\Programs\AZA Desktop' if (Test-Path $startMenuDir) { Remove-Item -Path $startMenuDir -Recurse -Force -ErrorAction SilentlyContinue Write-Ok "Startmenue-Eintraege entfernt." } $desktopShortcut = Join-Path ([Environment]::GetFolderPath("Desktop")) "AZA Desktop.lnk" if (Test-Path $desktopShortcut) { Remove-Item -Path $desktopShortcut -Force -ErrorAction SilentlyContinue Write-Ok "Desktop-Verknuepfung entfernt." } $publicDesktop = Join-Path $env:PUBLIC 'Desktop\AZA Desktop.lnk' if (Test-Path $publicDesktop) { Remove-Item -Path $publicDesktop -Force -ErrorAction SilentlyContinue Write-Ok "Oeffentliche Desktop-Verknuepfung entfernt." } } # --- Schritt 5: Firewall-Regel entfernen ---------------------------- function Remove-FirewallRule { Write-Step "4" "Firewall-Regel bereinigen" try { $existing = netsh advfirewall firewall show rule name="$AZA_FIREWALL_RULE" 2>&1 if ($existing -match "Regelname|Rule Name") { netsh advfirewall firewall delete rule name="$AZA_FIREWALL_RULE" 2>&1 | Out-Null Write-Ok "Firewall-Regel entfernt." } else { Write-Ok "Keine AZA-Firewall-Regel vorhanden." } } catch { Write-Skip "Firewall-Regel konnte nicht geprueft werden." } } # --- Schritt 6: Benutzerdaten (optional) ---------------------------- function Remove-UserData { param([bool]$DeleteUserData) Write-Step "5" "Benutzerdaten" if (-not $DeleteUserData) { Write-Ok "Benutzerdaten werden BEHALTEN." if (Test-Path $AZA_APPDATA_DIR) { Write-Host " AppData: $AZA_APPDATA_DIR" -ForegroundColor DarkGray } if (Test-Path $AZA_DOCS_DIR) { Write-Host " Dokumente: $AZA_DOCS_DIR" -ForegroundColor DarkGray } return } Write-Warn "Benutzerdaten werden GELOESCHT." if (Test-Path $AZA_APPDATA_DIR) { Write-Host " Entferne AppData: $AZA_APPDATA_DIR" -ForegroundColor White try { Remove-Item -Path $AZA_APPDATA_DIR -Recurse -Force -ErrorAction Stop Write-Ok "AppData entfernt (Profil, Einstellungen, Lizenz, Consent, Autotext, Stilprofile)." } catch { Write-Warn "Einige AppData-Dateien konnten nicht entfernt werden." Write-Host " $($_.Exception.Message)" -ForegroundColor DarkGray } } else { Write-Ok "Kein AppData-Verzeichnis vorhanden." } if (Test-Path $AZA_DOCS_DIR) { Write-Host " Entferne Dokumente: $AZA_DOCS_DIR" -ForegroundColor White try { Remove-Item -Path $AZA_DOCS_DIR -Recurse -Force -ErrorAction Stop Write-Ok "Dokumente entfernt (Transkripte, Briefe, Rezepte, Kostengutsprachen)." } catch { Write-Warn "Einige Dokument-Dateien konnten nicht entfernt werden." Write-Host " $($_.Exception.Message)" -ForegroundColor DarkGray } } else { Write-Ok "Kein Dokumente-Verzeichnis vorhanden." } } # --- Schritt 7: Registry-Reste pruefen ------------------------------ function Clean-RegistryRemnants { Write-Step "6" "Registry-Eintraege pruefen" $regPaths = @( "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\$($AZA_APP_ID)_is1", "HKLM:\SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall\$($AZA_APP_ID)_is1", "HKCU:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\$($AZA_APP_ID)_is1" ) $found = $false foreach ($rp in $regPaths) { if (Test-Path $rp) { try { Remove-Item -Path $rp -Recurse -Force -ErrorAction Stop Write-Ok "Registry-Eintrag entfernt: $rp" $found = $true } catch { Write-Warn "Registry-Eintrag konnte nicht entfernt werden: $rp" } } } if (-not $found) { Write-Ok "Keine AZA-Registry-Eintraege vorhanden." } } # --- Schritt 8: Abschlussbericht ------------------------------------ function Show-Summary { param([string]$Mode, [bool]$DeletedData) Write-Host "" Write-Host " =============================================" -ForegroundColor White Write-Host " ERGEBNIS" -ForegroundColor White Write-Host " =============================================" -ForegroundColor White Write-Host "" if ($Mode -eq "1") { Write-Host " Modus: Nur App entfernt" -ForegroundColor Green Write-Host " Benutzerdaten: BEHALTEN" -ForegroundColor Green } else { Write-Host " Modus: Vollstaendig zurueckgesetzt" -ForegroundColor Yellow Write-Host " Benutzerdaten: GELOESCHT" -ForegroundColor Yellow } Write-Host "" $needsRestart = $false $installDir = Find-InstallLocation if (-not $installDir) { $installDir = $INSTALL_DIR_DEFAULT } if (Test-Path $installDir) { Write-Warn "Installationsverzeichnis existiert noch (evtl. gesperrte Dateien)." Write-Host " Ein Neustart koennte noetig sein." -ForegroundColor DarkGray $needsRestart = $true } $azaStillRunning = Get-Process -Name $AZA_PROCESS_NAME -ErrorAction SilentlyContinue if ($azaStillRunning) { Write-Warn "AZA-Prozess laeuft noch! Bitte manuell schliessen oder PC neustarten." $needsRestart = $true } if ($needsRestart) { Write-Host "" Write-Host " NEUSTART: Moeglicherweise erforderlich (s. Hinweise oben)" -ForegroundColor Yellow Write-Host " NEUINSTALLATION: Nach Neustart moeglich" -ForegroundColor Yellow } else { Write-Host "" Write-Host " NEUSTART: NICHT erforderlich" -ForegroundColor Green Write-Host " NEUINSTALLATION: Sofort moeglich" -ForegroundColor Green } Write-Host "" $setupExe = $null $searchPaths = @( (Join-Path $PSScriptRoot '..\dist\installer\aza_desktop_setup.exe'), (Join-Path $PSScriptRoot '..\aza_desktop_setup.exe') ) foreach ($sp in $searchPaths) { if (Test-Path $sp) { $setupExe = (Resolve-Path $sp).Path break } } if ($setupExe) { Write-Host " Installer gefunden:" -ForegroundColor Cyan Write-Host " $setupExe" -ForegroundColor White Write-Host "" Write-Host " Zum Neuinstallieren einfach den Installer starten." -ForegroundColor White } else { Write-Host " Kein Installer im Projekt gefunden." -ForegroundColor DarkGray Write-Host " Bitte den neuen Installer manuell starten." -ForegroundColor DarkGray } Write-Host "" Write-Host " =============================================" -ForegroundColor White Write-Host "" } # --- Hauptablauf ---------------------------------------------------- function Main { Write-Banner $mode = Select-Mode $deleteData = ($mode -eq "2") if ($deleteData) { Write-Host "" Write-Host " ACHTUNG: Modus 2 loescht ALLE Benutzerdaten unwiderruflich!" -ForegroundColor Red Write-Host " (Profil, Transkripte, Briefe, Rezepte, Einstellungen, Signatur, Autotext)" -ForegroundColor Red Write-Host "" $confirm = Read-Host ' Wirklich fortfahren? [j/n]' if ($confirm -ne "j" -and $confirm -ne "J" -and $confirm -ne "ja" -and $confirm -ne "Ja") { Write-Host "" Write-Host " Abgebrochen." -ForegroundColor Yellow return } } Write-Host "" Write-Host " Starte Deinstallation..." -ForegroundColor White Stop-AzaProcesses $innoOk = Invoke-InnoUninstall Remove-InstallRemnants Remove-FirewallRule Remove-UserData -DeleteUserData $deleteData if (-not $innoOk) { Clean-RegistryRemnants } Show-Summary -Mode $mode -DeletedData $deleteData } Main