Berücksichtigung der Pending Files Rename queue (PFR) im Installationsprozess

Die „PendingFiles“-Problematik war am Rande schon einmal Thema dieses Blogs. Nichts desto trotz möchte ich mit diesem Artikel eine weitere Möglichkeit aufzeigen, wie Probleme im Zusammenhang mit dem Update von „in use“ Daten vermieden werden können.

 

   

Problematische Szenarien

Während in der Regel End User bei einer manuellen Installation von Windows Installer Setups mit User Interface zumindest durch den FileInUse, bzw. MsiRMFileInUse (ab Windows Installer 4.0) Dialog auf den Zustand hingewiesen werden, dass der Windows Installer zum erfolgreichen rebootfreien Installieren der Anwendung auf das Beenden von ausgewiesenen Programmen oder Prozessen angewiesen wäre, fehlt uns im Deployment diese Möglichkeit. Die Gründe dafür sind, dass zum einen Deploymentprozesse in der Regel nicht in einer interaktiven Benutzersession ablaufen, also auch ohne Anzeigemöglichkeit von Dialogen und andererseits werden sie in den meisten Fällen eh schon ohne Benutzerinterface gestartet, also mit entsprechenden „Silent switches“.  Wird msiexec.exe mit /q oder /qn ausgeführt, werden im Falle von lokalisierten „in use“ Daten diese über Mechanismen der Pending Files Rename queue (PFR) zum Ersetzen markiert. Im Windows Installer Logfile wird dies durch den Eintrag der Property ReplacedInUseFiles ersichtlich.

Negative Effekte entstehen dann, wenn im Anschluss an eine solche Installation der Computer nicht gebooted wird. Dies ist der Fall, wenn  die Property REBOOT auf „ReallySuppress“ steht und im Anschluss der Softewareverteilung keinen Computerneustart initiiert wird. Bei securityrelevanten Updates und Patches können solche Systeme bereits dann zu einem Sicherheitsrisiko werden, da gewisse Teile bei einem nicht vollzogenen Computerneustart ungepatched blieben. Noch schlimmer wird die Situation aber, wenn nach der Installation eines mit ReplacedInUseFiles beendeten Setups und vor dem nächsten Systemreboot erneut Windows Installer Installationen oder DeInstallationen durchgeführt werden. Und zwar solche, die Dateien ersetzten oder löschen möchten, welche sich bereits im Registrykey PendinfFileRenameOperations befinden. Dann nämlich, spätestens aber nach dem nächsten regulären Computerneustart entstünden Situationen, wo plötzlich wie von Geisterhand Dateien auf dem System entfernt (delete operation in PFR queue) oder downgegraded würden (update operation in PFR queue). Die Folge davon wären schliesslich nicht nachvollziehbare Störungen der installierten Software oder des Systems.

Lösungsansatz

Dies zu verhindern sollte unser aller Interesse sein. An sich müsste der Aufruf heissen, dass IMMER ein Computerneustart initiiert werden sollte, nachdem ReplacedInUseFiles gesetzt worden ist. In der Praxis ist dies im Deployment leider nicht immer möglich. Eine Möglichkeit, oben beschriebene Probleme zu umgehen, habe ich im Blogeintrag Welche Bedeutung hat der Windows Vista Restart Manager im Deployment aufgezeigt. Dort ging es um die Property MsiSystemRebootPending, die als LaunchCondition geprüft werden könnte. Wird diese LaunchCondition konsequent verwendet führt dies aber auch dazu, dass nach jedem einzelnen Eintrag im Registrykey PendinfFileRenameOperations keine einzige Installation mehr ausgeführt werden könnte, auch wenn die Einträge in der Registry in keinem Zusammenhang mit der aktuellen Installation stünden.

Es geht aber auch anders. Im folgenden Beispiel wird der Registrykey PendinfFileRenameOperations nur auf Dateien geprüft, die über die aktuelle Installationsinstanz ersetzt oder gelöscht werden sollten.  Dadurch werden keine Systeme zu einem Computerneustart durch Windows Installer Installationen „gezwungen“,  wenn nicht wirklich eine potentielle Gefahr durch ein Setup besteht. Auf der anderen Seite werden aber Installationen verhindert, die die oben beschriebenen Quereffekte nach sich ziehen könnten. Im Anhang finden Sie eine DLL CustomAction, die sich leicht in bestehende MSIs einpflegen lässt.

Vorgehen zur Implementation in die MSI

  1. Zunächst speichern Sie die folgende DLL auf Ihrem System ab.
     GetFilesInUse.dll
     
  2. …und setzen dann mit ORCA gleich eine Einschränkung, damit gewährleistet ist, dass die folgende MSI nur unter der richtigen Umgebung ausgeführt wird. Die DLL benötigt .NET Framework 2.0. Daher aus Sicherheitsgründen lieber gleich eine LaunchCondition setzen. Tragen Sie folgende Zeile in die LaunchCondition Tabelle
    pendingfiles3.jpg
      
  3. Integrieren Sie die DLL in der Binary Tabelle. Das Bild zeigt einen Ausschnitt aus ORCA.
    pendingfiles1.jpg
     

     
  4. Erstellen Sie in der CustomAction Tabelle einen Verweis auf die Binary mit dem Funktionsaufruf „GetFilesInUse“ in Target.

      
  5. Ordnen Sie diese CustomAction in der InstallExecuteSequence Tabelle nach InstallValidate ein. Nach dieser Action (InstallValidate) liegt durch den Costingprozess eine temporäre Tabelle im Speicher vor (Erweiterung der Component Tabelle), die Hinweise darauf gibt, welche Komponenten durch den aktuellen Installationsprozess installiert oder entfernt werden. Diese CustomAction funktioniert nur an dieser Position einwandfrei!
     
     
     
  6. Wird anschliessend das so modifizierte Setup mit einem verbose Logfile gestartet und befinden sich Ressourcen aus der aktuellen Installationsinstanz im Registry Key PendingFileRenameOperations, so finden wir über die Property PendingFiles die Dateien ausgewiesen, die in der PFR queue vorliegen. Im Falle von mehreren Dateien sind diese durch Semikolon „;“ getrennt. Die Property weist nur den Dateinamen (ohne Pfad) aus: PROPERTY CHANGE: Adding PendingFiles property. Its value is ‚H2F520S.EXE;H2520S.DLL‘.
     
  7. Diese Property kann nun in einer weiteren CustomAction geprüft und entsprechend darauf reagiert werden. In diesem Beispiel brechen wir das Setup über eine CustomAction Type 19 mit der Fehlermeldung „Files are in PendingFilesList“ ab. Die zusätzliche Action soll nur ausgeführt werden, wenn die Property PendingFiles gesetzt ist, daher wird in der InstallExecuteSequence Tabelle die Spalte Condition mit dem Eintrag PendingFiles ergänzt. Anbei sehen Sie die Implementationen in Orca:

     

     
  8. Et voilà . That’s it. 

Mit diesen einfachen Schritten haben wir ein robustes Installationsetup erhalten, welches abbricht, wenn sich Dateien aus der Installationssession in der PFR queue befinden. Wer die CustomAction CA_GetFilesInUse in seinem produktiven Umfeld einzetzen möchte, für den sind vielleicht folgende Erweiterungen noch hilfreich: Die Prüfung auf PendingFiles lässt sich durch eine weitere Property steuern. Durch EXCLUDEPENDINGFILES können Dateien aus der Prüfung ausgeschlossen werden. Auch dort sind nur Dateinamen ohne Pfadangaben anzugeben. Bei mehreren Dateien sind auch diese durch Semikolon zu trennen. Bspl. EXCLUDEPENDINGFILES = H2F520S.EXE;H2520S.DLL. Durch die Verwendung des Schlüsselwortes EXCLUDEPENDINGFILES=ALL kann für Einzelfälle oder zum Debugging  sogar die komplette Prüfung abgeschaltet werden.

Erweiterungen für Dateien, welche in Benützung sind

Aufmerksame Tester werden schnell feststellen, dass die DLL CustomAction noch andere Informationen bereithält. Zum Beispiel wird eine Property FilesInUse erstellt. Diese beinhaltet nach der Ausführung von CA_GetFilesInUse alle zurzeit exklusiv geöffneten Dateien, die von der Installationssession installiert oder gelöscht werden sollten. Man könnte so allfällige Problemstellungen bereits im Vorfeld erkennen. Vor allem hier machen Excludes Sinn. Mit der Property EXCLUDEFILESINUSE wäre eine Excludelist zu definieren, welche Dateien bei der Prüfung ignoriert werden sollen. Wie bekannt kann auch diese Property mit „ALL“ alle Dateien aus der Prüfung ausschliessen. Eine 100%ige Absicherung erreichen wir bei der alleinigen Verwendung der FilesInUse Property nicht, bzw. gibt es oft Situationen, wo die Property schon im normalen Umfeld Dateien „in use“ meldet, obwohl der Windows Installer diese Dateien regulär freigeben könnte. Dabei kann es sich um Abhängigkeiten von Services handeln (andere Dateien als ausführbare Dateien wie DLL, EXE, etc) oder um andere Elemente, die in Form eines Bootstrappers oder nicht datengesteuerten CustomActions auf das System übertragen würden. GetFilesInUse kann nur Komponenten, die in der Component Tabelle der MSI Datei deklariert sind, prüfen.

Dabei werden per Default auch alle Serviceressourcen, die über die ServiceInstall Tabelle installiert werden, mit deren zurzeit im Speicher geladenen Abhängigkeiten (alle Module) bei der Prüfung ausgeklammert. Trotzdem empfiehlt es sich bei Verwendung von MSIs mit Services über einen Vortest allfällige dauernd in der Property FilesInUse ausgewiesenen Dateien mit EXCLUDEFILESINUSE auszuschliessen.

Möchten Sie nun auch diese FilesInUse-Funktionalität in Ihre Setups einbauen, dann verwenden Sie einfach einen ähnlichen Mechanismus wie bei den PendingFiles dokumentiert.  

Fazit

Mit dem Einsatz solcher CustomActions machen Installationen endlich wieder Spass. Durch das Zweiphasenmodell (FilesInUse & PendingFiles) kann man nahezu alle Eventualitäten abdecken und Fast User Switching (FUS) sowie die Vorgabe, Installationen während Betriebszeiten auszuführen, machen uns auch keine Angst mehr. Dieser Blogeintrag sollte aber nicht missverstanden werden, hier geht es nicht um eine Empfehlung, ein System möglichst lange ohne Computerneustart betreiben zu können, sondern um mögliche Ansätze, um Probleme zu verhindern, wenn, aus welchen Gründen auch immer, diese Computerneustarts nicht gleich nach der einzelnen Softwareinstallation ausgeführt werden könnten.

A pros pos: Diese FilesInUse CustomAction funktioniert selbstverständlich auch sessionübergreifend und auf allen durch Windows Installer unterstützten Betriebssystemen ab Windows 2000 (vgl. Blog Welche Bedeutung hat der Windows Vista Restart Manager im Deployment). Einzige Abhängigkeit ist .NET 2.0, da die DLL als .NET Assembly realisiert und zur Verwendung aus dem Windows Installer durch Manipulationen über die Intermediate Language (Inverse Platform Invocation) exportiert wurde.

Download: GetFilesInUse.dll

Hinterlasse einen Kommentar