Pakete mit identischer ProductGUID entfernen

Hallo zusammen,

ich habe eine Frage zur Funktion RemovePackagesWithSameProductGUID. Ich möchte diese Funktion erstmals in einem bzw. zwei Paketen einsetzen. Wir verwenden Empirum für die Softwareverteilung.

Ich habe eine Anwendung, die einmal jährlich erscheint, sowie dazugehörige Service Packs, die monatlich veröffentlicht werden. Es handelt sich jeweils um Inno-Setups.

Meine Idee ist, zwei Pakete zu erstellen. Ein Paket für die Anwendung und ein separates Paket für die regelmäßigen Service Packs. Die Pakete haben eine einzigartige PackageGUID aber eine identische ProductGUID.

Das Problem ist, dass die Anwendung nach der Deinstallation eines Service Packs nicht mehr gestartet werden kann. Das Service Pack ersetzt einzelne Dateien im Programmverzeichnis. Bei der Deinstallation werden diese Dateien wieder entfernt und fehlen dadurch auch der eigentlichen Anwendung.

Ich würde deshalb gerne erreichen, dass bei einer Deinstallation, Installation oder Reinstallation der Anwendung automatisch alle zugehörigen Service Packs deinstalliert und deregistriert werden. Meine Idee war, im Paket der Anwendung RemovePackagesWithSameProductGUID = true zu setzen.

Im Service-Pack-Paket prüfe ich im Custom Begin, ob die Anwendung installiert ist. Falls nicht, wird die Installation mit einem Fehler beendet.

Bei einer Neuinstallation der Anwendung würde sich nichts ändern, da zu diesem Zeitpunkt noch kein Service Pack installiert sein kann. Wird die Anwendung deinstalliert, soll auch das Service Pack deinstalliert und das Paket deregistriert werden. Solange die Zuweisung des Service Packs bestehen bleibt, würde Empirum zwar weiterhin versuchen, das Paket zu installieren, die Installation würde aber aufgrund der Prüfung im Custom Begin fehlschlagen. Erst wenn die Zuweisung entfernt wird, würden diese Installationsversuche aufhören.

Interessant wird es bei einer Reinstallation der Anwendung. Meine Hoffnung war, dass dabei ebenfalls das Service Pack deinstalliert und deregistriert wird. Anschließend könnte Empirum das Service Pack automatisch wieder installieren. Dadurch müsste ich im Fehlerfall lediglich das Anwendungspaket neu installieren und nicht zusätzlich das Service-Pack-Paket anfassen.

Nach meinen bisherigen Tests scheint das bei der Deinstallation auch zu funktionieren. Bei einer Installation bzw. Reinstallation wird das Service Pack zwar deinstalliert, das Paket jedoch nicht deregistriert. Grundsätzlich kann ich dieses Verhalten nachvollziehen, für meinen Anwendungsfall wäre es allerdings unpraktisch.

Übersehe ich hier etwas oder gibt es für diesen Anwendungsfall einen besseren Ansatz?

Gruß

Hallo hartmann,

genau das war der ursprüngliche Ansatz daran, das eben nur bei einer Deinstallation quasi alle Pakete aus dieser per ProductGUID zusammengefassten Gruppe entfernt werden können.

Diese ganze Umsetzung mit einer solchen Gruppierung wird jedoch insgesamt schnell sehr komplex und man kann sie sich für diverse Szenarien überlegen.

So auch für Deinen Ansatz … aber die ursprüngliche Intension war mal die, dass man z.B. verschiedene Anwendungssprachen (Firefox deutsch und englisch) oder auch Architekturen (z.B. Adobe Reader 32bit und 64bit) hat und diese zuweisen kann, pro Maschine gewinnt die jeweils letzte Zuweisung (oder Reinstallation) und wenn man die gruppierten Anwendungen deinstalliert, verschwinden dann alle die zur Gruppe gehören. Das schließt aber das Szenario aus, das alle Gruppenmitglieder, die ein und derselben Gruppe zugeordnet sind neu installiert werden, weil eben die Registrierungen der anderen Gruppenmitglieder erhalten bleibt (weil damit das sonst möglicherweise auftretende Ping-Pong für die eigentliche Anwendung unterbunden wird).

Da sich das aber praktisch nicht unbedingt problemfrei anwenden lässt (da dies eben auch mit andere Anforderungen kollidiert und es auch schwierig ist, verschiedene definierten Gruppierungen leicht zu managen), bleibt dieses Feature ungenutzt und wird wahrscheinlich künftig auch komplett wieder verschwinden.

OK, was heisst das jetzt für Deinen Anwendungsfall. Ich denke man kann das nur extern lösen: D.h. eine Reinstallation kann für dieses Szenario leider nicht nur über die Hauptanwendung gesteuert werden, sondern muss dann wieder zweistufig erfolgen. Also die Hauptanwendung deinstallieren (diese entfernt auch die ServicePacks) und anschließend die Hauptanwendung und alle benötigten ServicePacks (was sich ja ggf. eh inzwischen geändert haben könnte) wieder zur Installation zuweisen. Wobei das ja nur im Fehlerfall relevant wäre. Es bleibt dann leider einzig der Vorteil, dass eine Deinstallation der Hauptanwendung hier eine Komplettbereinigung vornimmt, da halt alle Mitglieder mit dieser ProductGUID sauber entfernt werden. Für den Fall von mehreren ServicePacks sollte dann aber auch sichergestellt sein, dass diese alle entfernt werden können und es gibt dabei keine Möglichkeit der explizite Definition der Reihenfolge für die Deinstallation (was ja dann durchaus wichtig sein könnte)!

Also alles in allem ist dies dafür vielleicht dann doch keine wirklich brauchbare Umsetzung.

… somit ist wahrscheinlich die Steuerung über eine Zuweisungsgruppe in Empirum (und das Setzen der Reinstallation für alle Komponenten in der Zuweisungsgruppe im Fehlerfall) doch der einfachere Weg.

Gruß René.

Hallo @RKH.neo42,

vielen Dank für die ausführliche Antwort.

Ich hab mir nochmal Gedanken gemacht und mir überlegt, dass ich das aktuelle Service Pack Paket auch einfach manuell deinstallieren und deregistrieren könnte.

Das habe ich folgender Maßen abgebildet.

#region CustomBegin content
function script:Remove-StadtCadServicePack {
    # Der gleiche Wert steht in der Service-Pack-JSON im Feld "UninstallKey".
    [string]$spInnoKeyPath = 'HKLM:\Software\Microsoft\Windows\CurrentVersion\Uninstall\{SCGUID}_is1'
    [string]$spPackageGuid = '{042989F2-1677-4F0F-9835-D9A19DDDE0C9}'
    [string]$spAppName = "$($global:PackageConfig.AppName) Service Pack"

    if ($true -eq (Test-Path -Path $spInnoKeyPath)) {
        [string]$spUninstallerPath = (Get-RegistryKey -Key $spInnoKeyPath -Value 'UninstallString').Trim('"')
        Execute-Process -Path $spUninstallerPath -Parameters '/VERYSILENT /NORESTART /SUPPRESSMSGBOXES'
        Write-Log -Message "Uninstalled [$spAppName] via [$spUninstallerPath]." -Severity 1 -Source $deployAppScriptFriendlyName
    }

    Remove-RegistryKey -Key "HKLM:\Software\$($global:PackageConfig.RegPackagesKey)\$spPackageGuid" -Recurse
    Remove-RegistryKey -Key "HKLM:\Software\Microsoft\Windows\CurrentVersion\Uninstall\$spPackageGuid" -Recurse
    Remove-RegistryKey -Key "HKLM:\Software\$($global:PackageConfig.RegPackagesKey)\$($global:PackageConfig.AppVendor)\$spAppName" -Recurse
    Get-ChildItem -Path 'HKLM:\Software\Microsoft\Windows\CurrentVersion\Uninstall' -ErrorAction 'SilentlyContinue' |
        Where-Object { $_.PSChildName -like "neoPackage $($global:PackageConfig.AppVendor) $spAppName*" } |
        ForEach-Object {
            Remove-RegistryKey -Key ($_.Name -replace '^HKEY_LOCAL_MACHINE', 'HKLM:') -Recurse
        }

    [string]$spCacheDir = Join-Path -Path (Split-Path -Path (Split-Path -Path $global:PackageConfig.App -Parent) -Parent) -ChildPath $spAppName
    Remove-Folder -Path $spCacheDir
    Write-Log -Message "Removed package registration and cache [$spCacheDir] of [$spAppName]." -Severity 1 -Source $deployAppScriptFriendlyName
}

#endregion CustomBegin content

Die Funktion script:Remove-StadtCadServicePack rufe ich dann in CustomInstallAndReinstallPreInstallAndReinstall bzw. CustomUninstallBegin auf.

Meine Test waren alle positiv. Gibt es Gründe welche ich übersehe, warum ich das nicht so abbilden sollte?

Hallo @hartmann,

ja grundsätzlich spricht da nichts dagegen das so zu lösen.

Aber vielleicht wäre dies so doch eine elegantere Lösung - hatte ich gleich gar nicht auf dem Schirm - aber da es hier ja um die explizite Deinstallation eines anderen Paketes geht, läßt sich das auch über die DependentPackage-Option in der json steuern:

  "DependentPackages": [
    {
      "GUID": "{042989F2-1677-4F0F-9835-D9A19DDDE0C9}",
      "DesiredState": "Absent",
      "OnConflict": "Uninstall",
      "ErrorMessage": "ServicePack should be removed"
    }
  ],

Diese Bereinigung wird dann bei jeder Paketausführung im Installationsfall durchgeführt, allerdings auch im Softmigrationsfall - also auch dann, wenn die Anwendung dieses Paketes selbst als bereits installiert erkannt würde! Das ist aber im gedachten Szenario unerheblich …?! Der ServicePack würde dann erneut nachgezogen werden (sofern dauerhaft zugeordnet).

Der Fall Deinstallation wird dann doch durch die ursprünglich angedachte gleichgesetzte ProductGUID abgedeckt.

Gruß René.