Inspiriert von Rob Menschings historischer Blogserie ”Deciphering the MSI Directory table” und von Programmiertätigkeiten, wo ich auch auf Directoryinformationen angewiesen war, erlauben folgende Ausführungen einen kurzen Einblick in die Directory Tabelle und das Handling mit Directorybezeichnern in zwei Teilen.
Viele, die schon einmal einen Blick in die Directory Tabelle geworfen haben, werden sich über deren Aufbau gewundert haben. Meistens scheut man es, Verzeichnisse zur Kontrolle in Orca „per Hand“ aufzulösen und schaut daher lieber mal in den Editoren der Auringtools nach, wie ein entsprechendes Verzeichnis nun ausgeschrieben aussehen mag. Es gibt aber Situationen, wo wir uns über den Aufbau im Klaren sein müssen oder wo wir per Script den vollständigen Verzeichnisnamen benötigen. Für diese Zwecke und für das allgemeine Verständnis sind nachfolgende Zeilen gedacht:
In einer Windows Installer Datenbank finden wir Verzeichnisangaben in der Directory Tabelle. Alle Verzeichnisreferenzen aller Komponenten verweisen auf den Primary Key dieser Directory Tabelle und sind an sich Windows Installer Properties. Diese Tabelle wird schliesslich während des File Costing Prozesses durch Windows Installer ausgewertet.
Der Aufbau der Directory Tabelle
Die Directory Tabelle enthält drei Spalten, Directory, Directory_Parent und DefaultDir. Die Spalte Directory ist zugleich der Primary Key der Tabelle, d.h auch, dass dieser einen eindeutigen und einmalig vorkommenden Namen enthalten muss. Man sieht es bereits am Namen der Spalte Directory an, dass diese Spalte der Primary Key der Tabelle ist, da die Namen der Tabelle (Directory) und der Spalte (Directory) identisch sind. Bei Windows Installer Standard Tabellen, wo nur ein Primary Key vorkommt, wird oft in der Schlüsselspalte der selbe Name verwendet.
Eine Verzeichnisstruktur setzt sich aus dem Verweis auf einen Key in Directory_Parent und dem Unterverzeichnis (DefaultDir) zusammen. Das Auflösen der Directory_Parent erfolgt hierbei in mehreren Schritten maximal bis zu einem der Standardverzeichnisse, bis zu TARGETDIR (bzw. SourceDir) oder bis zu einem als public Property deklarierten Directory, welches durch AppSearch, CustomAction Typ 35 oder 51, durch die Commandline oder in der Property Tabelle definiert wurde. Abgeschlossen wird jede Verzeichnisangabe schliesslich durch ein Backslash „\“ am Ende der Zeichenkette.
Beispiel:
Top Level Verzeichnisse
Als Top Level Verzeichnisse werden hier Verzeichnisse benannt, die nicht weiter durch die Standardmechanismen aufgelöst werden müssen, da sie selbst durch Windows Installer während der Installation bestimmt werden. Diese Verzeichnisse bilden die “Root”, aber müssen sich aber nicht auf ein Root-Verzeichnis beschränken. Das Verzeichnis ProgramFilesFolder, welches auf “C:\Program Files” zeigen könnte, ist demnach beispielsweise ein Top Level Verzeichnis.
Die Auflösung der Top Level Verzeichnisse erfolgt durch Windows Installer auf verschiedene Art und Weise. Standardverzeichnisse werden wie die komplette Auswertung der Directory Tabelle auch innerhalb der Action CostFinalize aufgelöst. Diese werden dort aber durch die API Funktion SHGetFolderPath() ermittelt. Das Top Level Standardverzeichnis ProgramFilesFolder wird dabei beispielsweise mit der Zeichenkette “C:\Program Files\” gleichgesetzt und das LocalAppData Verzeichnis bekäme unter Windows Vista für eine Installation in meinem Kontext beispielsweise den Wert „C:\Users\oberlind\AppData\Local“.
In der Directory Tabelle verwendete public Properties werden hingegen durch die Action AppSearch, durch die Deklaration in der Property Tabelle, durch CustomActions Typ 35 oder 51, durch die Commandline oder durch das SetTargetPath() ControlEvent (bei full UI) deklariert. Für jedes verwendete Top Level Verzeichnis muss sich ein gültiger Eintrag in der Directory Tabelle befinden. Diese Deklaration wird aber während der Ausführung der MSI mit den „echten“ Werten überschrieben.
Beispiel mit Top Level Verzeichnissen TARGETDIR, ProgramFilesFolder und MYDATS:
Zielverzeichnisse nach dem FileCosting beim Installieren via
„msiexec.exe /i msi.msi MYDATS=C:\ProgramDat\Root“:
Man beachte, dass MYDATS automatisch ein Backslash angehängt wurde. Hätte man im Beispiel auf ein Verzeichnis mit Leerzeichen verweisen wollen, bspl. MYDAT=C:\Program Files\ProgramDat\Root, so wäre die Angabe von Anführungszeichen in der Commandline erforderlich gewesen:MYDATS=“C:\Program Files\ProgramDat\Root“.
TARGETDIR, SourceDir und ROOTDRIVE
Das Top Level Verzeichnis TARGETDIR bestimmt das Rootverzeichnis der Installation. TARGETDIR muss sich in der Directory Tabelle befinden, ansonsten erhält man Fehlermeldungen wie diese: „Root directory property undefined“. Die Deklaration muss hierbei folgenden Aufbau haben:
Falls der Inhalt von TARGETDIR bei der Installation nicht definiert wurde (beispielsweise über die Commandline), wird die Property ROOTDRIVE aufgelöst, um den Pfad zu ermitteln. Sollte auch ROOTDRIVE weder in der Property Tabelle noch über die Commandline angegeben worden sein, setzt Windows Installer bei einer Administrativinstallation diese Property auf das erste verfügbare und beschreibbare Netzwerklaufwerk. Bei einer Installation wird diese Property hingegen auf das Laufwerk mit dem grössten verfügbaren Speicherplatz gesetzt. Das sind die Gründe, warum im Deployment die Verwendung auf ROOTDRIVE=C:\ in der Property Tabelle empfohlen ist. Nichtbeachten dieser Regel kann dazu führen, dass eine Installation auf dem einen PC auf das lokale Laufwerk C:\ erfolgt, bei einem benachbarten Gerät hingegen auf Laufwerk D:\, wenn dort beispielsweise eine zweite Disk mit mehr Platz verfügbar ist.
Bei einer Administrativinstallation wird die Angabe von TARGETDIR in der Commandline empfohlen, da dadurch das Zielverzeichnis angegeben wird, wohin die Administrativinstallation erfolgen soll:
Msiexec.exe /a mymsi.msi TARGETDIR=H:\AdminP
Bei der Property SourceDir müssen keine expliziten Deklarationen in der Directory Tabelle erfolgen. SourceDir repräsentiert denn auch das Quellverzeichnis. Externe Cabinettdateien oder extern und unkomprimiert vorliegende Sourcedaten werden bei einer Installation oder Reparatur in diesem Verzeichnis gesucht. Auch CustomActions können aus diesem Verzeichnis ausgeführt werden oder auf dieses Verzeichnis über MsiGetProperty zugreifen. Die SourceDir Property wird über die Action ResolveSource, welche nach CostInitialize einzuordnen ist, initialisiert.
Tip: Möchten Sie alle Zugriffe bei einer Deinstallation auf das Installationsverzeichnis und allfällige SOURCELIST Verzeichnisse unterbinden, können Sie dies mit der Condition NOT REMOVE=“ALL“ bei ResolveSource in der InstallExecuteSequence Tabelle steuern.
Betrachtungen im Installationsprozess
Die Verzeichniseinträge werden während des Installationsprozesses in der Regel sowohl im Client-, als auch im Serverprozess ermittelt. Dabei werden die Verzeichniseinträge der Directory Tabelle während des File Costing Prozesses durch den DirectoryManager über das Installationsmodul des entsprechenden Prozesses ausgewertet.
Während dieser Phase werden die Directorybezeichner entsprechenden Properties zugewiesen. In einer Protokolldatei mit Verboseinformationen findet man daher nach der Ausführung von CostFinalize auch ein Dump dieser ermittelten Verzeichnisse.
Fortsetzung folgt…
Inside Directories in Windows Installer Teil 2/2



