MSI-Custom Actions in Rust
Verfasst: 14.03.2024, 18:23
Vorweg, dieses ist keines der üblichen Tutorials zum AKInstallerMSI, sondern richtet sich eher an Programmierer.
Die Programmiersprache Rust ist aktuell in aller Munde und wird von vielen gelobt und, wie soll es anders sein, von anderen verteufelt.
Rust hat gegenüber den anderen üblichen Hochsprachen wie Java und C# (inkl. .NET allgemein) einen großen Vorteil. Es ist sehr schnell, kaum zum Absturz zu bewegen und braucht vor allem keine Runtimes! Bietet aber bereits ein Baukastenprinzip an, also einfach hinzuzufügenden Funktionen, man muss also nicht alles allein und selbst tun.
In der Programmierung von Custom Actions wird hauptsächlich C, C++ und C# oder auch PowerShell verwendet. C# weil .NET angesprochen wird oder weil die Dokumentation für Windows hauptsächlich .NET-Beispiele bietet und alles, was dann doch C++ ist, benötigt wieder irgendwelche anderen Voraussetzungen. Oder nutzt neue Funktionen, die auf älteren Systemen nicht vorhanden sind, so dass man sich mutig durch den COM-Dschungel kämpfen muss, um die gleiche Funktionalität auf diesen Systemen hin zu bekommen. Was in C# häufig mit wenig Code zu bewerkstelligen ist. Microsoft mag C/C++ nicht, könnte man meinen.
Wie aber erwähnt, sollten Custom Actions keine Voraussetzungen benötigen, doch das Wichtigste ist, sie dürfen niemals abstürzen! Ausnahmen müssen abgefangen werden (.NET und modernes C++ werfen damit bekanntlich nur so um sich) und die Routine muss sicher beendet werden, andernfalls scheitert eine Installation oder noch schlimmer eine Deinstallation, dazu später mehr.
In beiden Fällen ist der Zielrechner möglicherweise in einem nicht gewollten Zustand, der nicht dem MSI-Konzept entspricht. Sprich eine Systemänderung wird durch einen Umkehrvorgang nicht zurückgenommen.
Das Erstellen und Testen von Custom Actions ist sehr umständlich, man kann die Funktion zwar außerhalb erstellen und testen, von dort die MSI-Datenbank auslesen und alles so weit vorbereiten. Aber dann intern als DLL im MSI kommt es immer mal wieder vor, dass ein MSIHANDLE oder sonstiger Speicher nicht freigegen wurde oder irgendwo doch eine Ausnahme auftritt, weil irgendwas doch einen nullptr zurückliefert oder sonstiges geschieht, was man noch nicht berücksichtig hat.
Viele Custom Actions arbeiten zudem zweistufig. Die Erste liest die Daten aus der MSI-Datenbank oder verwendet Einstellungen der GUI, verpackt diese in irgendeine Form, sorgt für die Rollback-Schritte und überträgt diese an die zweiten Stufen (mehrzahl), wo dann verzögert die Abarbeitung stattfindet (De/Installation / Rollback / Commit). Dieses lässt sich häufig nicht mehr extern simulieren, dazu muss die (fast) fertige CA-DLL in ein MSI mit entsprechenden Daten verpackt und dort debuggt werden.
Dazu ein Tipp: Eine Deinstallationsroutine sollte immer ERROR_SUCCESS zurück liefern und Fehler auf andere Weise melden. Und niemals das Debuggen direkt mit Abschießen des Prozesses beenden! Nichts ist ärgerlicher als ein Fehler, der die Deinstallation verhindert und man dadurch das Produkt nicht mehr vom Rechner bekommt. Wo wir wieder bei der Fehlerbehandlung, Ausnahmen oder Abstürze sind.
Rust hat ein sehr strenges Typen-Konzept und dadurch erst einmal eine sehr gewöhnungsbedürftige Syntax (dies war mein erster Eindruck, wenn man erst mal über „Hallo Welt“ hinaus ist), ist aber – wenn man den Code kompiliert bekommt – fast nicht zum Absturz zu bewegen und halt schnell. Nicht wie C/C++ oder gar Assembler aber schneller als C# oder Java (ok für Custom Actions eh ungeeignet) allemal. Und ja, Schnelligkeit kann in Custom Actions wichtig sein. Man erinnere sich vielleicht an ein früheres Visual Studio-Update, das über eine Stunde für die Migration benötigt hat.
Aus diesen Gründen werden einige Routinen in Linux und Windows und .NET bereits zu Rust portiert oder sind es bereits.
Zeit für Rust in MSI-Custom Actions. Hierfür finden Sie im Anschluss zwei Links, einer zu einer Möglichkeit Rust in Custom Actions zu betreiben, der andere zu einem deutschsprachigen Rust Tutorial.
Viel Spaß dabei!
Die Programmiersprache Rust ist aktuell in aller Munde und wird von vielen gelobt und, wie soll es anders sein, von anderen verteufelt.
Rust hat gegenüber den anderen üblichen Hochsprachen wie Java und C# (inkl. .NET allgemein) einen großen Vorteil. Es ist sehr schnell, kaum zum Absturz zu bewegen und braucht vor allem keine Runtimes! Bietet aber bereits ein Baukastenprinzip an, also einfach hinzuzufügenden Funktionen, man muss also nicht alles allein und selbst tun.
In der Programmierung von Custom Actions wird hauptsächlich C, C++ und C# oder auch PowerShell verwendet. C# weil .NET angesprochen wird oder weil die Dokumentation für Windows hauptsächlich .NET-Beispiele bietet und alles, was dann doch C++ ist, benötigt wieder irgendwelche anderen Voraussetzungen. Oder nutzt neue Funktionen, die auf älteren Systemen nicht vorhanden sind, so dass man sich mutig durch den COM-Dschungel kämpfen muss, um die gleiche Funktionalität auf diesen Systemen hin zu bekommen. Was in C# häufig mit wenig Code zu bewerkstelligen ist. Microsoft mag C/C++ nicht, könnte man meinen.
Wie aber erwähnt, sollten Custom Actions keine Voraussetzungen benötigen, doch das Wichtigste ist, sie dürfen niemals abstürzen! Ausnahmen müssen abgefangen werden (.NET und modernes C++ werfen damit bekanntlich nur so um sich) und die Routine muss sicher beendet werden, andernfalls scheitert eine Installation oder noch schlimmer eine Deinstallation, dazu später mehr.
In beiden Fällen ist der Zielrechner möglicherweise in einem nicht gewollten Zustand, der nicht dem MSI-Konzept entspricht. Sprich eine Systemänderung wird durch einen Umkehrvorgang nicht zurückgenommen.
Das Erstellen und Testen von Custom Actions ist sehr umständlich, man kann die Funktion zwar außerhalb erstellen und testen, von dort die MSI-Datenbank auslesen und alles so weit vorbereiten. Aber dann intern als DLL im MSI kommt es immer mal wieder vor, dass ein MSIHANDLE oder sonstiger Speicher nicht freigegen wurde oder irgendwo doch eine Ausnahme auftritt, weil irgendwas doch einen nullptr zurückliefert oder sonstiges geschieht, was man noch nicht berücksichtig hat.
Viele Custom Actions arbeiten zudem zweistufig. Die Erste liest die Daten aus der MSI-Datenbank oder verwendet Einstellungen der GUI, verpackt diese in irgendeine Form, sorgt für die Rollback-Schritte und überträgt diese an die zweiten Stufen (mehrzahl), wo dann verzögert die Abarbeitung stattfindet (De/Installation / Rollback / Commit). Dieses lässt sich häufig nicht mehr extern simulieren, dazu muss die (fast) fertige CA-DLL in ein MSI mit entsprechenden Daten verpackt und dort debuggt werden.
Dazu ein Tipp: Eine Deinstallationsroutine sollte immer ERROR_SUCCESS zurück liefern und Fehler auf andere Weise melden. Und niemals das Debuggen direkt mit Abschießen des Prozesses beenden! Nichts ist ärgerlicher als ein Fehler, der die Deinstallation verhindert und man dadurch das Produkt nicht mehr vom Rechner bekommt. Wo wir wieder bei der Fehlerbehandlung, Ausnahmen oder Abstürze sind.
Rust hat ein sehr strenges Typen-Konzept und dadurch erst einmal eine sehr gewöhnungsbedürftige Syntax (dies war mein erster Eindruck, wenn man erst mal über „Hallo Welt“ hinaus ist), ist aber – wenn man den Code kompiliert bekommt – fast nicht zum Absturz zu bewegen und halt schnell. Nicht wie C/C++ oder gar Assembler aber schneller als C# oder Java (ok für Custom Actions eh ungeeignet) allemal. Und ja, Schnelligkeit kann in Custom Actions wichtig sein. Man erinnere sich vielleicht an ein früheres Visual Studio-Update, das über eine Stunde für die Migration benötigt hat.
Aus diesen Gründen werden einige Routinen in Linux und Windows und .NET bereits zu Rust portiert oder sind es bereits.
Zeit für Rust in MSI-Custom Actions. Hierfür finden Sie im Anschluss zwei Links, einer zu einer Möglichkeit Rust in Custom Actions zu betreiben, der andere zu einem deutschsprachigen Rust Tutorial.
Viel Spaß dabei!