Ein eigenes Setup mit WiX

Prolog

Im letzten Artikel Besser Bauen mit FAKE wurde darauf hingewiesen, dass die in FAKE integrierten Möglichkeiten zum Bauen eines Setups begrenzt sind. Statt dessen wurde durch das Build-Skript MSBuild mit einem WiX-Projekt als Target angestoßen. Um den Aufbau dieses Installer-Projekts geht es in diesem Post.

 

Nach Download und Installation des Windows Installer XML Toolkits wird ein neues Setup-Projekt angelegt. Da die Projektumgebung alle installierbaren Pakete enthält, genügt ein einzelnes Projekt im Verzeichnis Setup. Gleichzeitig ergibt sich daraus schon der prinzipielle Aufbau des Installers: einzelne Komponenten sollen abwählbar sein, der Installer selbst soll mehrsprachig sein und die Versionsnummer des Buildsystems soll berücksichtigt werden.

 

Der Projektrahmen

Durch den Projekt-Wizard wurde bereits das grundlegende XML-Gerüst angelegt. Wir erweitern die Informationen um die Versionsnummer sowie die Sprachunterstützung:

<Wix xmlns=http://schemas.microsoft.com/wix/2006/wi

xmlns:util=“http://schemas.microsoft.com/wix/UtilExtension&#8220;> <!– Produkt-Definition –> <Product Id=“85d37c9c-685c-41b7-a996-e2c6d92031b6″ UpgradeCode=“f6f2968f-d114-44b9-874e-4f32ffe64427″ Manufacturer=“Slesa Solutions“ Name=“!(loc.ProductName)“ Language=“!(loc.Language)“ Version=“$(var.ProductVersion)“ Codepage=“utf-8″>

Die gezeigten GUIDs sollten selbstverständlich durch eigens generierte ersetzt werden.

Es folgen die Beschreibung des Pakets wie dessen Systemvoraussetzungen…

    <!-- Package-Definition -->
    <Package InstallerVersion="200" 
             Manufacturer="Slesa Solutions"
             Compressed="yes"
             Description="!(loc.ProductDescr)"
             Comments="(c) 2011 Slesa Solutions"
             InstallPrivileges="elevated"
             />

    <!-- Requirements -->
    <PropertyRef Id="NETFRAMEWORK40FULL" />
    <Condition Message="!(loc.ErrorFramework)">NETFRAMEWORK40FULL</Condition>
    <Condition Message="!(loc.ErrorAdminRights)">Privileged</Condition>

… das Installer-Paket soll innerhalb einer Cabinet-Datei abgelegt werden…

    <Media Id="1" Cabinet="media1.cab" EmbedCab="yes" />

… und die Installation soll unterhalb des Programme-Verzeichnisses erfolgen

    <Directory Id="TARGETDIR" Name="SourceDir">
      <Directory Id="ProgramFilesFolder">
        <Directory Id="APPLICATIONFOLDER" Name="Poseidon" />
      </Directory>
      <Directory Id="DesktopFolder"/>
    </Directory>

Falls später noch Verknüpfungen auf dem Desktop abgelegt werden sollen, sollten die dort hinterlegten Icons an dieser Stelle definiert werden. Sie verweisen auf Bitmaps im Resources-Verzeichnis, das ebenfalls zum Projekt gehört:

    <Icon Id="I__BackOfficeIcon.exe" SourceFile="Resources\Poseidon.ico" />
    <Property Id="PRODUCTICON" Value="I__BackOfficeIcon.exe"/>

Die Komponenten

Mit dem Backoffice-Projekt im Hinterkopf können wir jetzt die installierbaren Komponenten auflisten. Die Dateien beziehen wir dabei aus dem Ziel-Ordner des Build-Skripts:

    <DirectoryRef Id="APPLICATIONFOLDER" FileSource="..\..\bin\build">

Wir beginnen mit den unverzichtbaren Dateien als Shared Components

      <Component Id="C__SharedComponents" Guid="b81ad615-4091-49a9-ab09-d0da690bcb04" DiskId="1">
        <File Id="F__CaliburnMicro" Name="Caliburn.Micro.dll" />
        <File Id="F__FLuentNHibernate" Name="FluentNHibernate.dll" />
        <File Id="F__IesiCollections" Name="Iesi.Collections.dll" />
        <File Id="F__NHibernate" Name="NHibernate.dll" />
        <File Id="F__Interactivity" Name="System.Windows.Interactivity.dll" />
      </Component>

Es folgt das Backoffice-Programm selbst, dass die übrigen Module nachlädt. Hier ist auch der oben erwähnte Shortcut auf den Desktop

<Component Id=“C__BackOffice“ Guid=“{C46D1942-3C5C-4edf-8E06-36D48DFD8892}“ DiskId=“1″> <File Id=“F__BackOffice“ Name=“BackOffice.exe“ KeyPath=“yes“ />

<File Id=“F__BackOfficeCfg“ Name=“BackOffice.exe.config“ /> <File Id=“F__BackOfficeContract“ Name=“BackOffice.Contracts.dll“ /> <File Id=“F__BackOfficeTheme“ Name=“BackOffice.Theme.dll“ /> <File Id=“F__ModelShared“ Name=“Model.Shared.dll“ /> <File Id=“F__PersistenceShared“ Name=“Persistence.Shared.dll“ /> <Shortcut Id=“S__BackOffice“ Directory =“DesktopFolder“ WorkingDirectory=“APPLICATIONFOLDER“ Name=“Poseidon BackOffice“ Icon=“I__BackOfficeIcon.exe“ Advertise=“yes“ Description=“!(loc.BackOfficeDescription)“ /> </Component>

und die drei Office-Module – Benutzer-, POS- sowie die Bestandsverwaltung

      <Component Id="C__BackOfficeIcs" Guid="{613F262E-156E-49FD-82F7-31F659F1511C}">
        <File Id="F__IcsModel" Name="Ics.Model.dll" />
        <File Id="F__IcsNHibernate" Name="Ics.NHibernate.dll" />
        <!-- File Id="F__IcsOfficeModule" Name="Ics.OfficeModule.dll" / -->
        <File Id="F__IcsResources" Name="Ics.Resources.dll" />
      </Component>
      
      <Component Id="C__BackOfficeUms" Guid="{A8A43C44-526D-487F-9319-855EA5BCF725}">
        <File Id="F__UmsModel" Name="Ums.Model.dll" />
        <File Id="F__UmsNHibernate" Name="Ums.NHibernate.dll" />
        <File Id="F__UmsOfficeModule" Name="Ums.OfficeModule.dll" />
        <File Id="F__UmsResources" Name="Ums.Resources.dll" />
      </Component>

      <Component Id="C__BackOfficePms" Guid="{BF7884AB-D67D-4773-B69B-6CFD563727B2}">
        <File Id="F__PmsModel" Name="Pms.Model.dll" />
        <File Id="F__PmsNHibernate" Name="Pms.NHibernate.dll" />
        <File Id="F__PmsOfficeModule" Name="Pms.OfficeModule.dll" />
        <File Id="F__PmsResources" Name="Pms.Resources.dll" />
      </Component>

    </DirectoryRef>

Es sei noch einmal darauf hingewiesen, daß es sich hierbei nur um die Auflistung der Dateien handelt. Der Installationsumfang wird noch einmal gesondert als Features angegeben.

 

Die Features

Nachdem die Komponenten und die darin enthaltenen Dateien definiert wurden, können sie von den Features referenziert werden. Zu beachten ist, dass hier bereits ein Abhängigkeitsbaum angegeben wird – ohne Office-Komponente auch keine Office-Module:

    <Feature Id="SharedFiles" Level="1" InstallDefault="local" 
             Absent="disallow" AllowAdvertise="no" TypicalDefault="install"
             Title="!(loc.SharedFeatureTitle)"
             ConfigurableDirectory="APPLICATIONFOLDER"
             Description="!(loc.SharedFeatureDescription)">
      <ComponentRef Id="C__SharedComponents" />
    </Feature>

    <Feature Id="BackOffice" Level="1" Display="expand" 
             InstallDefault="local" AllowAdvertise="no"
             Title="!(loc.BackOfficeFeatureTitle)"
             Description="!(loc.BackOfficeFeatureDescription)">
      <ComponentRef Id="C__BackOffice" />

      <Feature Id="BackOfficeUms" Level="1" InstallDefault="local" AllowAdvertise="no"
             Title="!(loc.BackOfficeUmsFeatureTitle)"
             Description="!(loc.BackOfficeUmsFeatureDescription)">
        <ComponentRef Id="C__BackOfficeUms" />
      </Feature>
      <Feature Id="BackOfficePms" Level="1" InstallDefault="local" AllowAdvertise="no"
             Title="!(loc.BackOfficePmsFeatureTitle)"
             Description="!(loc.BackOfficePmsFeatureDescription)">
        <ComponentRef Id="C__BackOfficePms" />
      </Feature>
      <Feature Id="BackOfficeIcs" Level="1" InstallDefault="local" AllowAdvertise="no"
             Title="!(loc.BackOfficeIcsFeatureTitle)"
             Description="!(loc.BackOfficeIcsFeatureDescription)">
        <ComponentRef Id="C__BackOfficeIcs" />
      </Feature>
      
    </Feature>

Ab hier sind dem Installer alle Dateien bekannt, es erfolgt lediglich noch die Anpassung der Setup-Oberfläche. Die Installation soll pro Maschine statt pro Benutzer erfolgen, es wird eine abzunickende Lizenz angegeben, die Bitmaps werden ausgetauscht, und die anzuzeigenden Wizard-Seiten werden angegeben:

    <Property Id="ApplicationFolderName" Value="Poseidon" />
    <Property Id="WixAppFolder" Value="WixPerMachineFolder" />

    <WixVariable Id="WixUILicenseRtf" Value="license.rtf"/>
    <WixVariable Id="WixUIDialogBmp" Value="$(sys.SOURCEFILEDIR)\Resources\WixUI_Bitmap.jpg" />
    <WixVariable Id="WixUIBannerBmp" Value="$(sys.SOURCEFILEDIR)\Resources\WixUI_Banner.jpg" />

    <UIRef Id="WixUI_ErrorProgressText" />
    <UIRef Id="WixUI_Advanced" />

  </Product>
</Wix>

 

Die Übersetzung

Ein beherzter Versuch, das Projekt zu kompilieren, schlägt leider fehl. Es wurden bereits Übersetzungs-Platzhalter verwandt, die es zuerst in einer Sprache anzugeben gilt. Wir fügen dem Projekt also noch zwei Wix Localization Files hinzu, hier 1031.wxl und 1033.wxl benannt nach den Windows Locale Codes. In diesen wird die Sprache angegeben, sowie die lokalisierten Strings, z.B.:

<?xml version=“1.0″ encoding=“utf-8″?> <WixLocalization Culture=“de-de“ xmlns=“http://schemas.microsoft.com/wix/2006/localization&#8220;> <String Id=“Language“>1031</String>

<String Id=“ProductName“>Poseidon</String> <String Id=“ProductDescr“>Poseidon – eine POS-Umgebung</String>

<String Id=“BackOfficeDescription“>BackOffice zum Bearbeiten der Stammdaten</String> <String Id=“SharedFeatureTitle“>Benötigte Dateien</String> <String Id=“SharedFeatureDescription“>Von den Anwendungen gemeinsam benutze Dateien und Komponenten.</String> <String Id=“BackOfficeFeatureTitle“>BackOffice</String> <String Id=“BackOfficeFeatureDescription“>Backoffice zum Bearbeiten der Daten und Beziehungen.</String> <String Id=“BackOfficeUmsFeatureTitle“>User Management System</String> <String Id=“BackOfficeUmsFeatureDescription“>Modul zur Verwaltung von Benutzers und Benutzerrechten.</String> <String Id=“BackOfficePmsFeatureTitle“>POS Management System</String> <String Id=“BackOfficePmsFeatureDescription“>Modul zur Verwaltung der POS-Umgebung.</String> <String Id=“BackOfficeIcsFeatureTitle“>Inventory Control System</String> <String Id=“BackOfficeIcsFeatureDescription“>Modul zur Verwaltung von Bestandszählern.</String> <String Id=“ErrorAdminRights“>Die Installation von [ProductName] erfordert administrative Privilegien.</String> <String Id=“ErrorFramework“>Microsoft .NET Framework wurde nicht gefunden. [ProductName] benötigt das .NET Framework 4.0.</String> </WixLocalization>

Mit diesem WiX-Skript steht nun bereits ein recht angenehmer Setup-Mechanismus zur Verfügung, um eigene Programme auf fremde Platten zu bannen. Angenehmer wäre es jedoch, wenn man eigene Grundeinstellungen ebenfalls eingeben könnte. In unserem Fall wäre dies z.B. der Connect-String für die Datenbank.

 

Eigene Optionen

Durch Auswahl einer der UI-Referenzen WixUI_Mondo, WixUI_Advanced oder WixUI_FeatureTree hat man bereits eine kleie Auswahl an Gestaltungsmöglichkeiten für die Oberfläche des Installers. Um jedoch eigene Seiten einzuarbeiten, um etwa einen Pfad eintragen zu lassen, muß der komplette Ablauf der Oberfläche umdefiniert werden.

Hierfür ist es zu allererst notwendig, bereits bestehende Referenzen wieder aus der Product.wxs zu entfernen, da sie sonst doppelt definiert sind. Dies betrifft die Zeilen

<!--<WixVariable Id="WixUILicenseRtf" Value="license.rtf"/>-->
<!--<WixVariable Id="WixUIDialogBmp" Value="$(sys.SOURCEFILEDIR)\Resources\WixUI_Bitmap.jpg" />-->
<!--<WixVariable Id="WixUIBannerBmp" Value="$(sys.SOURCEFILEDIR)\Resources\WixUI_Banner.jpg" />-->

sowie die bisher benutzte Oberfläche

<!--<UIRef Id="WixUI_Mondo" />-->
<!--<UIRef Id="WixUI_Advanced" />-->
<!--<UIRef Id="WixUI_FeatureTree" />-->

Sie werden durch folgende Zeile ersetzt

<UIRef Id="CustomUI_Mondo" />

Und diese Art der Oberfläche definieren wir jetzt.

 

Eine eigene Datenbankseite

Wie beginnen mit dem Layout der eigenen Optionsseite, im vorliegenden Fall der Eingabemöglichkeit des Datenbank-Verbindungsstrings. Hierfür müssen unter WiX die einzelnen Komponenten des Dialogs – ähnlich WinForms – innerhalb des Dialogs positioniert werden. Es gibt auch Vorgaben bezüglich der Fenstergrößen oder der Position der einzelnen Buttons.

Für das Installer-Skript kommen 2 zusätzliche Fragmente hinzu, ich habe die neue Datei dem Anlaß entsprechend DbConnectionDlg.wxs genannt. Der Header bereitet wieder alles für WiX vor

<?xml version="1.0" encoding="UTF-8"?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">

Jetzt folgt der neue Dialog als erstes Fragment. Die ID des Dialogs wird später als Referenz benötigt, sie sollte also sinngemäß sein. Der Layout wurde dem der übrigen Dialoge angepaßt:

<Fragment>

  <UI Id="CustomUIExtension">

    <Dialog Id="DbConnectionDlg" Width="370" Height="270" Title="!(loc.DbConnectionTitle)">
      <Control Id="Next" Type="PushButton" X="236" Y="243" Width="56" Height="17" Default="yes" Text="!(loc.WixUINext)">
        <Condition Action="disable"><![CDATA[DBCONNECTION = ""]]></Condition>
        <Condition Action="enable"><![CDATA[DBCONNECTION <> ""]]></Condition>
      </Control>
      <Control Id="Back" Type="PushButton" X="180" Y="243" Width="56" Height="17" Text="!(loc.WixUIBack)" />
      <Control Id="Cancel" Type="PushButton" X="304" Y="243" Width="56" Height="17" Cancel="yes" Text="!(loc.WixUICancel)">
        <Publish Event="SpawnDialog" Value="CancelDlg">1</Publish>
      </Control>

      <Control Id="Description" Type="Text" X="25" Y="23" Width="280" Height="15" Transparent="yes" NoPrefix="yes" Text="!(loc.DbConnectionDescr)" />
      <Control Id="Title" Type="Text" X="15" Y="6" Width="200" Height="15" Transparent="yes" NoPrefix="yes" Text="{\WixUI_Font_Title}!(loc.DbConnectionTitle)" />
      <Control Id="BannerBitmap" Type="Bitmap" X="0" Y="0" Width="370" Height="44" TabSkip="no" Text="!(loc.InstallDirDlgBannerBitmap)" />
      <Control Id="BannerLine" Type="Line" X="0" Y="44" Width="370" Height="0" />
      <Control Id="BottomLine" Type="Line" X="0" Y="234" Width="370" Height="0" />

      <Control Id="LblDbConnection" Type="Text" X="20" Y="60" Width="240" Height="12" NoPrefix="yes" Text="!(loc.DbConnectionStr)" />
      <Control Id="EditDbConnection" Type="Edit" X="20" Y="75" Width="240" Height="18" Property="DBCONNECTION" Indirect="no" />

    </Dialog>
  </UI>

</Fragment>

Man beachte die Beeinflussung der Darstellung des Dialog-Titels durch {\WixUI_Font_Title}!(loc.DbConnectionTitle) und das Verhindern einer leerer Eingabe durch die Conditions des Next-Buttons.

Dieser neue Dialog ist nun natürlich durch nichts mit den anderen verknüpft, es muß also eine Aufruf-Reihenfolge definiert werden. Diese bildet das zweite Fragment. Das UI-Element darin muß die selbe ID bekommen, die wir bereits als neue Oberfläche definiert haben, nämlich CustomUI_Mondo. Daneben sind alle Definitionen zu treffen, die die Standard-Oberflächen uns vormals abgenommen haben:

<Fragment>

  <UI Id="CustomUI_Mondo">
    <TextStyle Id="WixUI_Font_Normal" FaceName="Tahoma" Size="8" />
    <TextStyle Id="WixUI_Font_Bigger" FaceName="Tahoma" Size="12" />
    <TextStyle Id="WixUI_Font_Title" FaceName="Tahoma" Size="9" Bold="yes" />

    <Property Id="DefaultUIFont" Value="WixUI_Font_Normal" />
    <Property Id="WixUI_Mode" Value="Mondo" />

wir definieren unsere benötigte Variable für die Datenbankverbindung

    <Property Id="DBCONNECTION" Value="Server=.\SQLEXPRESS;initial catalog=Poseidon;Integrated Security=SSPI" Secure="yes">
      <RegistrySearch Id="Reg__DbConnection" Key="SOFTWARE\!(loc.ProductName)" Root="HKLM" Type="raw" Name="DbConnection" />
    </Property>

Wir referenzieren die benutzten Dialoge des Installers

     <DialogRef Id="ErrorDlg" />
      <DialogRef Id="LicenseAgreementDlg" />
      <DialogRef Id="FatalError" />
      <DialogRef Id="FilesInUse" />
      <DialogRef Id="MsiRMFilesInUse" />
      <DialogRef Id="PrepareDlg" />
      <DialogRef Id="ProgressDlg" />
      <DialogRef Id="ResumeDlg" />
      <DialogRef Id="UserExit" />

und verknüpfen nun die verschiedenen Dialoge miteinander:

  • der Exit-Dialog beendet den Installer
  • Der Willkommens-Dialog zum Lizenzabkommen
  • Das Lizenzabkommen führt zurück zum Willkommens-Dialog, und weiter zur Auswahl des Installationsortes
  • Die Installationsort-Nachfrage führt zurück zur Lizenz und weiter zu unserem eigenen Dialog. Daneben kann noch ein neuer Dialog zur Verzeichnisauswahl aufgerufen werden
  • Unsere Datenbank-Dialog führt zurück zum Installationsort und weiter zur Paketauswahl
  • Die Paketauswahl führt zurück zur Datenbank-Anbindung und weiter zum Sind-Sie-Sicher-Dialog
  • Der Sind-Sie-Sicher-Dialog führt zurück zum Paketauswahl-Dialog

Das hört sich zwar kompliziert an, läßt sich aber genau so auch hinschreiben

    <Publish Dialog="ExitDialog" Control="Finish" Event="EndDialog" Value="Return" Order="999">1</Publish>

    <Publish Dialog="WelcomeDlg" Control="Next" Event="NewDialog" Value="LicenseAgreementDlg">1</Publish>
      
    <Publish Dialog="LicenseAgreementDlg" Control="Back" Event="NewDialog" Value="WelcomeDlg">1</Publish>
    <Publish Dialog="LicenseAgreementDlg" Control="Next" Event="NewDialog" Value="InstallDirDlg">1</Publish>

    <Publish Dialog="InstallDirDlg" Control="Back" Event="NewDialog" Value="LicenseAgreementDlg">1</Publish>
    <Publish Dialog="InstallDirDlg" Control="ChangeFolder" Property="_BrowseProperty" Value="[WIXUI_INSTALLDIR]" Order="1">1</Publish>
    <Publish Dialog="InstallDirDlg" Control="ChangeFolder" Event="SpawnDialog" Value="BrowseDlg" Order="2">1</Publish>
    <Publish Dialog="InstallDirDlg" Control="Next" Event="SetTargetPath" Value="[WIXUI_INSTALLDIR]" Order="1">1</Publish>
    <Publish Dialog="InstallDirDlg" Control="Next" Event="NewDialog" Value="DbConnectionDlg" Order="2">1</Publish>

    <Publish Dialog="DbConnectionDlg" Control="Back" Event="NewDialog" Value="InstallDirDlg">1</Publish>
    <Publish Dialog="DbConnectionDlg" Control="Next" Event="NewDialog" Value="CustomizeDlg">1</Publish>

    <Publish Dialog="CustomizeDlg" Control="Back" Event="NewDialog" Value="DbConnectionDlg">1</Publish>
    <Publish Dialog="CustomizeDlg" Control="Next" Event="NewDialog" Value="VerifyReadyDlg">1</Publish>
               
    <Publish Dialog="VerifyReadyDlg" Control="Back" Event="NewDialog" Value="CustomizeDlg">1</Publish>

Das mag einem als viel Arbeit vorkommen, weil man ja eigentlich “nur den einen Dialog” dazwischen schieben wollte. Man darf aber nicht vergessen, daß sich gleichzeitig auch die komplette Reihenfolge der Dialoge, aber auch das Weglassen der selben auf ziemlich einfachen Weg realisieren läßt.

Der Connection-String zur Datenbank kann wird nun abgefragt – aber wie kommt er zum Programm? Bei unserer ersten Variante des Installers haben wir uns schon die Konfigurationsdatei des Backoffices mitinstallieren lassen. Jetzt können wir die nach der Installation verändern, z.B. den erfragten String einzutragen. Dieser Vorgang gehört zur Komponente C__BackOffice und geschieht nach dem Erstellen des Shortcuts auf dem Desktop:

        <Shortcut ...
        ...>

        <util:XmlFile Id="X__DbConnection" Action="setValue"
                      Permanent="yes"
                      ElementPath="/configuration/appSettings/add[\[]@key='DbConnection'[\]]"
                      File="[#F__BackOfficeCfg]" Name="value"
                      Value="[DBCONNECTION]"  Sequence="1" />


      </Component>

Hier sehen wir übrigens auch den Grund, warum im WiX-Skript der util-Namensbereich registriert wurde.

Nun werden an dieser Stelle noch die Variablen definiert, die wir aus dem Haupt-Skript herausgenommen haben:

  </UI>

  <UIRef Id="WixUI_Common" />

  <WixVariable Id="WixUIDialogBmp" Value="$(sys.SOURCEFILEDIR)\Resources\WixUI_Bitmap.jpg" />
  <WixVariable Id="WixUIBannerBmp" Value="$(sys.SOURCEFILEDIR)\Resources\WixUI_Banner.jpg" />
  <WixVariable Id="WixUILicenseRtf" Value="license.rtf"/>

</Fragment>


</Wix>

3 übersetzbare Strings kamen auch noch hinzu, diese sind auf die beiden Sprachdateien 1033.wxl und 1031.wxl zu verteilen:

<String Id="DbConnectionTitle">Konfiguration der Datenbank-Verbindung</String>
<String Id="DbConnectionDescr">An dieser Stelle können Sie den Verbindungs-String bearbeiten </String>
<String Id="DbConnectionStr">Connection-String:</String>

Nach dem Kompilieren sollte nun ein MSI-Installer zur Verfügung stehen, der nicht nur die Datenbank-Verbindung nachfragt, sondern sie auch in die Konfigurationsdateien der entsprechenden Programme, hier das Backoffice, einträgt.

 

Fazit

Pro Sprache wird nun ein eigenes MSI-File erzeugt. Zwar gibt es auch Mittel und Wege, um alle Installer in ein großes Setup-Packet zu packen, andererseits spart sich so auch etwas Bandbreite.

Meines Erachtens gibt es mit den WiX-Tools keine Ausreden mehr, warum ein Programm per Copy-Befehl installiert werden sollte. Wenn man keine eigenen Konfigurationen vornehmen lassen will, ist mit wenigen Zeilen Code ein Setup gezaubert. Sollen doch noch Werte nachgefragt werden, ist der Aufwand auch nicht sehr viel größer.

Zum Continuous Delivery fehlt nun nur noch das automatische Ausrollen per Ftp, sowie das automatische Erstellen eines Newsletters, in dem die Release-Notes aus der Quellcode-Verwaltung extrahiert werden. Aber das steht wieder in einem ganz anderen Artikel…

DotNetKicks-DE Image
Dieser Beitrag wurde unter .NET, Installer, WiX veröffentlicht. Setze ein Lesezeichen auf den Permalink.

3 Antworten zu Ein eigenes Setup mit WiX

  1. Anselme Tueno schreibt:

    Sehr Gute Einführung für WiX. Für den Einsteiger wäre einen Absatz über Compiler(candle) und Linker(light) hilfreich gewesen.
    Vielen Dank

  2. mreukauff schreibt:

    Link zum Image ist tot

Hinterlasse einen Kommentar