Nun für was genau ist dieser Beitrag? In meiner Firma wollen wir unser Setup dynamisch mit Wix erstellen, ich weiß Tallow wäre dafür wohl auch ein guter Weg aber das ist nicht das was wir vor haben. Wir wollen ein .wxs File als Vrolage her nehmen und dieses dann für das Setup unseres Programms anpassen. Sicher gäbe es auch die Möglichkeit das ganze on the fly zu erstellen aber das schon uns nicht die Sauberste Lösung. Als Beispiel nehmen wir der Einfachheit halber eine etwas abgespeckte .wxs Datei die im Beispielprojekt von Wix Dabei ist. Unsere Vorlage würde dann also so aussehen:
<?xml version=’1.0′ encoding=’windows-1252′?>
<Wix xmlns=’http://schemas.microsoft.com/wix/2006/wi’>
<Product Name=’Foobar 1.0′ Id=’YOURGUID-86C7-4D14-AEC0-86416A69ABDE’
Language=’1033′ Codepage=’1252′ Version=’1.0.0′ Manufacturer=’Acme Ltd.’>
<Package Id=’*’ Keywords=’Installer’ Description=“Acme’s Foobar 1.0 Installer“
Comments=’Foobar is a registered trademark of Acme Ltd.’ Manufacturer=’Acme Ltd.’
InstallerVersion=’100′ Languages=’1033′ Compressed=’yes’ SummaryCodepage=’1252′ />
<Media Id=’1′ Cabinet=’Sample.cab’ EmbedCab=’yes’ DiskPrompt=“CD-ROM #1″ />
<Property Id=’DiskPrompt’ Value=“Acme’s Foobar 1.0 Installation [1]“ />
<Directory Id=’TARGETDIR’ Name=’SourceDir’>
<Directory Id=’ProgramFilesFolder’ Name=’PFiles’>
<Directory Id=’Acme’ Name=’Acme’>
<Directory Id=’INSTALLDIR’ Name=’Foobar10′ LongName=’Foobar 1.0′>
</Directory>
</Directory>
</Directory>
</Directory>
</Product>
</Wix>
Für die Leute die Fit in xml sind dürfte das alles kein Großer Aufwand sein, oder zumindest keine große Magie, da das .wxs File in dem alle Informationen festgelegt sind auch nur eine XML Datei mit einer anderen Endung ist. Nun ja in jedem fall brauchen wir zuerst einmal das XML Dokument in unserer Anwendung, was recht einfach über die folgende Zeilen zu realisieren ist:
XmlTextReader reader = new XmlTextReader(„C:\\wixSetup\foobar.wxs“);
XmlDocument doc = new XmlDocument();
doc.Load(reader);
Als nächstes kommt ein Schritt den wir benötigen um eine Hürde zu umgehen die uns das Wix Dokument in den Weg legt nämlich der Namespace. Dieser ist bei der .wxs ein anderer als bei einer Standard XML Datei. Aber dafür gibt es den XmlNameSpaceManager, in diesem können wir Später z.B. unserer Suchfunktion übergeben damit diese weiß wie sie in dem XML suchen muss doch dazu später mehr. Wenn wir den Manager anlegen erwartet er zunächst eine XmlNameTable diese bekommen wir über die Eigenschaft NameTable von unserem XML Dokument. Als nächstes müssen wir noch den Namespace hinzufügen den wir verwenden wollen, dies geht über die Funktion AddNamespace beim XmlNamespaceManager. Diese erwartet von uns das wir ein Prefix angeben und ein Namespace (in unserem Fall „wi“ und „http://schemas.microsoft.com/wix/2006/wi“) im Code sieht das ganze dann so aus:
XmlNamespaceManager nsmgr = new XmlNamespaceManager(doc.NameTable);
nsmgr.AddNamespace(„wi“, „http://schemas.microsoft.com/wix/2006/wi“);
Gut jetzt haben wir das Dokument und einen NamespaceManager, aber was wollen wir nun machen? Nun wollen wir sehr wahrscheinlich entweder einen bereits Vorhanden Eintrag aktualisieren oder einen neuen Eintrag vor nehmen. Gehen wir zuerst einmal von ersteren aus. Nehmen wir einmal an wir wollen die Versionsnummer des Programms von „1.0.0“ auf „1.0.1“ ädern. Was brauchen wir dafür? Nun zuerst müssen wir uns einmal die Entsprechende Zeile aus dem Dokument holen, auch Node genannt. Hierfür gibt es eine Funktion namens bei unserem XmlDocument welche sich SelectSingleNode nennt und als Übergabeparameter einen XPath String erwartet sowie optional einen XmlNamespaceManager damit er weiß wie er suchen muss (da war doch vorhin etwas nicht?). XPath ist eine art SQL für XML Dateien, mit ihr kann man Auswallen aus dem Dokument laden. In unserem Fall sieht das ganze folgendermaßen aus:
XmlNode packageNode = doc.SelectSingleNode(„//wi:Product“, nsmgr);
Jetzt haben wir die Node und was machen wir nun damit? Nun jede Node hat ein Attribute Property in diesem sind alle Dinge wie ID, Name, usw gespeichert, als nächstes müssen wir uns also das passende Attribute suchen und dessen Wert ändern. Da wir ja wissen das unser Attribbute Version heißt ist es recht einfach es in der Attribute Liste zu finden da der Name gleichzeitig der Schlüssel des Attributes ist, es sieht also folgendermaßen aus:
packageNode.Attributes["Version"].Value = „1.0.1″;
Gut, jetzt haben wir eine vorhandene Node bearbeitet, aber wie sieht es aus wenn wir eine Komplett neue Node hinzufügen wollen? Nehmen wir an wir wollen eine neue Component hinzufügen, was müssen wir dafür tun? Nun zu nächst einmal brauchen wir die Node unter der wir sie hinzu fügen Wollen. Anschließend müssen wir eine neue XmlNode erstellen, dies geht über die Funktion CreateElement von unserem XmlDocument. Dieser Funktion müssen wir dann den Namen der Node übergeben (z.B. Directory, Media, Component, usw.). Anschließend müssen wir der Node noch die Passenden Attribute hinzufügen, diese erzeugen wir über die Funktionen CreateAttribute von unserem XmlDocument, diese erwartet nur den Namen des Attributs. Anschließend müssen wir die neuerstellte Node der übergeordneten mit der Funtkion AppendChild hinzufügen. Im Code würde alles so aussehen:
XmlNode directoryNode = doc.SelectSingleNode(„//wi:Directory[@Id='INSTALLDIR']„, nsmgr);
XmlNode newComponentNode = doc.CreateElement(„Component“, „http://schemas.microsoft.com/wix/2006/wi“);
newComponentNode.Attributes.Append(doc.CreateAttribute(„Id“)).Value = „FooBar“;
newComponentNode.Attributes.Append(doc.CreateAttribute(„Guid“)).Value = „YOUR GUID HERE“;
directoryNode.AppendChild(newComponentNode);
So, was bleibt am Schluss noch zu tun? Nun jetzt müssen wir nur noch alle Änderungen speichern, dies funktioniert über die Funktion Save unseres XmlDocumenst der wir einen Pfad angeben müssen, hier sollten wir eine neue Datei angeben da wir unsere Vorlage ja nicht überschreiben wollen
doc.Save(„C:\\wixSetup\\foobar.wxs“);
So ich hoffe das hilft den ein oder anderem, wenn etwas noch unklar ist einfach fragen..