Probleme mit Deployment-Projekten im Visual Studio


Thomas Wölfer
Thomas Wölfer

05. Juni 2008


Im Visual Studio (2005) gibt es eine Projektart vom Typ "Deployment" - damit kann man "ganz einfache" Installationsprogramme auf Basis des Windows Installers erzeugen. Nachdem wir zwar ein sehr großes Projekt haben, dessen Installation aber im wesentlichen eigentlich auch per XCopy durchgeführt werden könnte, nehmen wir keines der großen Installer-Pakete her, sondern verwenden einfach das im Studio eingebaute.

Der einzige Luxus der einem dabei geboten wird, sind "Custom Setup Actions": Man kann eine (so man will, managed) DLL produzieren die verschiedene Eintrittspunkte für Installationsereignisse wie "Install", "Uninstall" oder "Rollback" hat. Man muss nicht alle implementieren - und wir benutzen auch nur einen davon: Beim installieren der Software überprüft der "Custom" Step, ob sich an der Stelle auf dem Quellmedium, an der sich auch der Installer befindet, eine Lizenzdatei befindet. Ist das der Fall, dann wird die Datei in einen Ordner des Zielsystems kopiert.

Soweit, so gut - und eigentlich völlig klar. Wenn es da nicht ein Problem wäre: Hat man bereits eine Programmversion installiert und versucht dann, eine neue zu installieren - dann schlägt das fehl. Oder um genau zu sein: Die Installation der Folgeversion klappt auch, aber wenn man dann versucht selbige zu starten, dann startet statt dessen der Windows Installer und bietet an, die Installation zu reparieren.

Ich habe eine ganze Menge Stunden gebraucht um dahinter zu kommen, was genau passiert - denn wenn man vor der Installation der "Nachfolgeversion" die "Vorgängerversion" manuell deinstalliert, dann klappt alles.

Nun arbeite ich genauso mit dem Windows Installer wie jeder andere lokale Installer-Guru, nur eben ohne jegliches Fachwissen: Die im folgenden geschilderten Vorgänge können also stimmen oder nicht - ich habe sie mir in der Tat einfach nur so "zusammengereimt".

Folgendes passiert: Wenn eine Nachfolgeversion installiert wird und die passende Eigenschaft gesetzt ist (was bei mir der Fall war), dann deinstalliert der Windows Installer zunächst die Vorgängerversion und installiert dann die Nachfolgeversion. Das geschieht aber in einem Programmlauf.

Wenn man nun eine CustomInstallerStep.dll verwendet, dann muss diese DLL zum deinstallieren vom Installer geladen werden, damit der "Uninstall" Step daraus durchgeführt werden kann. Handelt es sich um eine "managed code" DLL, dann kann der Installer diese DLL aber nicht mehr entladen, nachdem der Custom Step durchgeführt wurde. Grund: Die Assembly der DLL ist in den vom Installer verwendeten CLR Raum geladen - und von dort kann man Assemblies nicht entladen. Sie verschwinden erst, wenn auch der Prozess der die CLR nutzt verschwindet.

Nun soll die "alte" DLL aber im Zuge der Deinstallation entfernt werden. Das geht aber nicht, weil Sie noch geladen ist. Dem Installer-Prozess bleibt also nichts anderes übrig, als sich zu "merken", das diese DLL "ganz am Ende" noch gelöscht werden muss. (Ich vermute, das der Installer dazu in zwei Prozesse aufgeteilt ist, wobei der "innere" die CLR nutzt, der äußere aber nicht.).

Ist nun die Deinstallation vollzogen, dann befindet sich die CustomStep DLL weiterhin ungelöscht auf der Platte. Es folgt nun die Installation der neuen Programmversion. Ich vermute, das in deren Zuge die "alte" DLL von der neuen überschrieben wird. (Auch stark geraten: Glaube, das man nicht löschen, aber sehr wohl überschreiben kann.). Danach ist dann die Installation vollständig, und die benutzte CLR wird vom Installer entladen. (Oder aber, der "innere" Installer wird beendet und in diesem Zuge wird die CLR entladen - der Effekt ist aber der gleiche.).

Nachdem die CLR jetzt nicht mehr geladen ist, ist auch die Custom Step DLL nicht mehr blockiert - und also wird sie nun im allerletzten Schritt der Installation gelöscht. Ergebnis: Die Installation hat zwar "funktioniert" - sieht aber mangels einer fehlenden Datei nicht so aus, wie sie aussehen sollte. Genau darum bemängelt der Installer die Installation dann später.

Wie gesagt: Alles ein wenig geraten - wenn mir jemand besser erklären kann, wie das zusammenhängt: Immer her mit der Erklärung :-)

Achso - es gibt eine Lösung: Man markiert die CustomStep DLL im Setup-Projekt so, das sie eben nicht mit deinstalliert wird: dann bleibt zwar beim deinstallieren ein wenig "Schmutz" auf der Platte zurück - dafür kann man aber überhaupt eine Deinstallation durchführen.