Seite 1 von 1

Mehrfaches Ausführen von Programmen während der Installation

Verfasst: 12.05.2023, 13:35
von Andreas Kapust
Inspiration für dieses Tutorial ist ein reales Kundenprojekt, bei dessen Umsetzung wir beraten haben und das im Folgenden etwas abgewandelt wird, um für die Allgemeinheit anwendbarer zu sein.
Ausgangsbasis war ein bestehendes MSI-Paket welches mit einem anderen Tool erstellt und dann im AKInstallerMSI eingelesen wurde.

Folgende Voraussetzungen waren gegeben:
  • A: Die Exe (im Weiteren als Worker.exe oder EXE bezeichnet) sollte drei Mal ausgeführt werden, jeweils mit dem Schalter /Start 1|2|3 und vollen Rechten.
  • B: Die 1. Ausführung mit dem Schalter / Start 1 soll vor der Installation ermitteln, ob es eine Vorversion gibt und ggf. einen Dateipfad (z. B. Datenbankpfad) sichern (dieser steht in der Registry).
  • C: Die Vorversion soll sauber deinstalliert werden, ohne dass der Windows Installer irgendwelche alten Daten bearbeitet.
  • D: Die 2. Ausführung muss nach InstallFiles (das ist eine Sequenz im MSI) ausgeführt werden, Schalter /Start 2.
  • E: Die 3. Ausführung soll am Ende der Installation ausgeführt werden um abschließende Aktionen (Aufräumen) auszuführen, Schalter /Start 3.
  • F: Kommende Versionen sollen immer mit einem neuen ProductCode versehen werden.
  • G: Es soll kein zusätzlicher Code dafür geschrieben werden, keine DLL und kein Powershell-Skript oder was auch immer.
Diese Vorgaben schränken einige Dinge ein.

Die allgemeine Anlaufstelle für die Ausführen von Programmen ist Benutzerdefinierte Aktionen (oder Custom Action).
Bild In diesem Fall benötigt die Worker.exe aber eine INI-Datei, welche im gleichen Ordner liegen muss, aber per Custom Action kann immer nur eine Datei in den Sequenzen untergebracht werden.

Aufruf per installierte Dateien scheidet komplett aus.

Ein selbst extrahierendes Archiv wäre möglich, müsste allerdings den Returncode der Worker.exe zurück liefern und dürfte darum auch nicht nach dem Entpacken sofort zurückkehren.
Dieses sind einige Dingen, warum schlußendlich ein anderer Weg genommen wurde.

Vorüberlegungen:

Punkt C verlangt eine saubere Deinstallation, ohne dass das neue MSI von Altlasten geplagt wird.
Der erste Aufruf Punkt B muss aber vor der Deinstallation erfolgen.

Für den Aufruf der Worker.exe wird eine zusätzliche INI-Datei im gleichen Ordner benötigt, darum scheidet in beiden unten genannten Möglichkeiten der Variante, die Exe in den Ressourcen unterzubringen, aus und es wird die Funktion Temporäre Daten verwendet, welche in der Install Execute Sequence an Position 1510 aufgerufen wird.

An diesem Punkt gibt es zwei Möglichkeiten. Man teilt die Aufgaben auf den Bootstrapper und MSI-Custom Actions auf (dieser Weg wird im Beispiel genutzt) oder alle drei Aufrufe der Worker.exe erfolgen einzig über Custom Actions.

Alle Aufrufe erfolgen über Custom Action:

Auch wenn der Weg nicht benutzt wird, wird die Vorgehensweise hier kurz erklärt. Es wird dazu aber etwas mehr MSI-Interna benötigt.

Eine Deinstallation bestehender Installationen wird im Allgemeinen durch RemoveExistingProducts nach der Installation der neuen Daten ermöglicht (Position 6650).
Hierbei werden alle nicht mehr benötigten Komponenten der vorherigen Installationen entfernt, welches auch in den meisten Fällen die richtige Vorgehensweise bedeutet.

Um Punkt C (die saubere Deinstallation) zu gewährleisten, muss die MSI-Funktion RemoveExistingProducts an den Anfang verlegt werden. Update/Produkt-Codes -> Erst die alten Daten deinstallieren und dann die neue Version installieren verlagert RemoveExistingProducts von 6650 auf die Position 1450 und damit auch vor das Extrahieren der temporäre Daten.

Aufteilung auf Bootstrapper und MSI-Custom Actions:

Bild

Hierbei wird der erste Aufruf und die Deinstallation im Bootstrapper untergebracht und der 2. und 3. Aufruf geschieht per Custom Actions im MSI.
Im Bootstrapper werden im Folgenden die Seiten Daten suchen, Deinstallation von Vorversionen und Konfiguration verwendet.


Konfiguration (Bootstrapper-Teil):

Bild

Daten suchen wird verwendet, um den ersten Start mittels Konfiguration abhängig davon zu machen, ob überhaupt eine Vorgängerversion gefunden wird.

Die Suche erfolgt nach dem UpgradeCode, als Eigenschaft wird der Name SUCHE_ALTES_MSI genutzt und die Daten bequem ausgelesen.

Durch [RESULT] wird SUCHE_ALTES_MSI auf 1 gesetzt (Mehr dazu in der Anleitung), wenn der UpgradeCode auf dem Zielsystem gefunden wird.

Hat das Vorgänder-MSI es richtig gemacht, liefert [RESULT_PATH] den Installationspfad (nicht jedes Authoring-Tools beherrscht das) und man könnte auch diesen verwenden. Im Weiteren wird angenommen, das SUCHE_ALTES_MSI mit [RESULT_PATH] initialisiert wird, ein einfaches [RESULT] (also der Wert 1) reicht aber auch.

Bild

Im Bild sieht man, wie dieser Installationspfad mittels /InstallPath "[SUCHE_ALTES_MSI]" übergeben wird (Anführungstriche, weil SUCHE_ALTES_MSI ein Pfad ist). Hierzu muss die Eigenschaft nur in eckigen Klammern angegeben werden.
Der komplette Aufruf lautet (siehe Vorgaben) /Start 1 /InstallPath "[SUCHE_ALTES_MSI]" .

Weiterhin wird SUCHE_ALTES_MSI als Bedingung für die eigentliche Ausführung der EXE eingetragen, ist SUCHE_ALTES_MSI nicht gesetzt, wird die EXE nicht aufgerufen.

Bild

Die Deinstallation ist schnell angelegt, die Daten werden einfach über den im Bild markierten Schalter bequem ausgelesen.

Bild

Optional kann SUCHE_ALTES_MSI auch an das MSI übergeben werden. Hierzu wird im Parameter SUCHE_ALTES_MSI=[SUCHE_ALTES_MSI]" angegeben (Anführungsstriche, weil [RESULT_PATH] genutzt wird). Falls es irgendwie nötig ist, kann der Update-Parameter, wie im Bild, ebenfalls erweitert werden.

Konfiguration (MSI-Teil):

Bild

Die folgenden Einstellungen erfolgen ohne Assistenten oder Vorlagen, allein durch den Aufruf von Eintrag anlegen per Ribbon oder Kontextmenü.

Bild

Die Übergabe von SUCHE_ALTES_MSI an die Worker.exe ist optional, wichtig ist nur /Start2.

Im Dialog wird der Speicherort der EXE -] In einem bekannten Verzeichnis gewählt. [TempFolder]Datenentpacken ist später auch der Ort, an dem die temporären Daten entpackt werden sollen (siehe unten) und damit die korrekte Vorgehensweise.

Parameter entspricht den Vorgaben /Start 2 /InstallPath "[SUCHE_ALTES_MSI]".

Der Zeitpunkt und Kontext wird, wie im Bild zusehen, auf Verzögerte Ausführung im Systemkontext gesetzt, weil volle Rechte benötigt werden und dieses nach dem Entpacken ausgeführt werden soll, was wiederum verzögert in der Ausführungsschicht geschieht.

Der Bezeichner (oben) kann beliebig benannt werden, z. B. WorkerExeStarten2 für den zweiten (ersten im MSI) Aufruf.

Bild

Die Ausführung erfolgt in der Install Execute Sequence. Diese ist die Sequenz, die die eigentliche Installation ausführt und zwar zweigeteilt. Eine Schicht die die Daten sammelt und ein Ablaufskript erzeugt und eine Schicht, die dieses ausführt.

Klicken Sie auf diese Sequenz und im Anschluss auf Auswählen. Über die Lupe kann nach InstallFiles (siehe Vorüberlegungen) gesucht ober einfach bis zur Sequenz 4000 gescrollen werden. Dort reicht es, irgendeinen Eintrag nach 4000 und Ok anzuklicken.

Durch die Bedingungen muss noch geregelt werden, das dieser Aufruf nur wenn SUCHE_ALTES_MSI gesetzt ist und nur bei einer Installation (keiner Deinstallation) erfolgen soll: SUCHE_ALTES_MSI AND NOT REMOVE.


Durch die Einstellung wird diese Aktion nur ausgeführt, wenn SUCHE_ALTES_MSI gesetzt ist, welches entweder vom Bootstrapper an das MSI übergeben wurde oder alternativ mittels MSI-Bordmitteln durch eine Startvorausetzung -] Datensuche gesetzt werden kann. Darauf wird aber an dieser Stelle nicht weiter eingegangen.

Bild

Nach dem Klick auf Ok erscheinen unten zwei Warnungen. Die erste, welche besagt das TempFolder auf der Seite Dateien & Verzeichnisse nicht angelegt ist, wird entfernt indem das Arbeitsverzeichnis auf INSTALLDIR geändert wird, oder Tempfolder bei Dateien & Verzeichnisse angelegt wird.. Hintergrund: Das Arbeitsverzeichnis muss in der Tabelle Directory (Seite Dateien & Verzeichnisse) definiert sein, ansonsten kommt bei der Ausführung des Setups der Fehler 2727.

Nach dem Abschluss aller Einstellungen und dem Bestätigen mittels Ok, wird per Ribbon oder Kontextmenü eine Kopie des Eintrags angelegt.
Welche nur wenige Abweichungen hat, den Bezeichner (WorkerExeStarten3), den Parameter /Start 3 /InstallPath "[SUCHE_ALTES_MSI]" und die Plazierung in den Sequenzen.

Die 3. Ausführung soll ganz am Ende erfolgen, z. B. MsiPublishAssemblies, damit die Aktion nach 6250 aber (wichtig) vor 6610 eingetragen wird (dem Entfernen der temporären Daten) unter Bedingungen wird wieder SUCHE_ALTES_MSI angeben.

Bild

Die Einstellung der temporären Daten ist recht einfach, beide Dateien werden in [TempFolder]Datenentpacken entpackt und als Bedingung wird SUCHE_ALTES_MSI genutzt. Am Ende sollten alle Dateien wieder entfernt werden.

Bild

Und damit Punkt F nicht vergessen wird, zum Abschluss eine Hinweis mit Wiedervorlage.