264 Stimmen

WiX Tricks und Tipps

Wir verwenden schon seit einiger Zeit WiX und trotz der üblichen Schwierigkeiten bei der Benutzerfreundlichkeit läuft es recht gut. Was ich suche, sind nützliche Ratschläge zu folgenden Themen:

  • Einrichten eines WiX-Projekts (Layout, Verweise, Dateimuster)
  • WiX in Lösungen und Build-/Release-Prozesse integrieren
  • Installationsprogramme für neue Installationen und Upgrades konfigurieren
  • Irgendwelche nützlichen WiX-Tricks, die Sie teilen möchten

0 Stimmen

Blicken Sie sich gui4wix.codeplex.com an

10 Stimmen

Als nicht konstruktiv geschlossen? Ich habe eine Menge gelernt, indem ich diese Frage gestellt habe! Ein wenig Konsistenz von StackOverflow wäre auch schön...z.B. stackoverflow.com/questions/550632/…

15 Stimmen

Es bekam '203' Likes, das reicht aus, um seine Nützlichkeit zu beweisen.

18voto

si618 Punkte 16160

Erstellen von Live-, Test-, Schulungs-, ... Versionen unter Verwendung derselben Quelldateien.

Kurz gesagt: Erstellen Sie für jeden Installer einen eindeutigen UpgradeCode und definieren Sie automatisch den ersten Zeichen jedes Guid für jeden Installer, wobei die verbleibenden 31 eindeutig sind.

Voraussetzungen

Annahmen

  • WiX-Variablen werden verwendet, um UpgradeCode, ProductName, InstallName zu definieren.
  • Sie haben bereits einen funktionierenden Installer. Ich würde dies nicht versuchen, bis Sie dies haben.
  • Alle Ihre Komponenten werden in einer Datei (Components.wxs) aufbewahrt. Dieser Prozess funktioniert, wenn Sie mehrere Dateien haben, es wird nur mehr Arbeit zu tun geben.

Verzeichnisstruktur

  • Setup.Library
    • Alle wxs-Dateien (Komponenten, Features, UI-Dialoge, ...)
    • Common.Config.wxi (ProductCode="*", ProductVersion, PlatformProgramFilesFolder, ...)
  • Setup.Live (wixproj)
    • Verknüpfen Sie alle Setup.Library-Dateien über "Vorhandene Datei hinzufügen" -> "Als Verknüpfung hinzufügen" (die kleine Pfeiltaste direkt neben der Schaltfläche Hinzufügen in Visual Studio)
    • Config.wxi (hat eindeutigen UpgradeCode, ProductName, InstallName, ...)
  • Setup.Test, ...
    • wie Live, aber Config.wxi ist für die Testumgebung konfiguriert.

Prozess

  • Erstellen Sie das Verzeichnis Setup.Library und verschieben Sie alle wxs- und wxi-Dateien (außer Config.wxi) aus dem vorhandenen Projekt.
  • Erstellen Sie Setup.Live, Setup.Test, usw. wie gewohnt mit wixproj.
  • Fügen Sie in Setup.Live usw. das BeforeBuild-Ziel hinzu, um die MSBuild-Community-Aufgabe FileUpdate auszuführen, um Guids zu ändern (Ich habe A für Live, B für Test und C für Schulung verwendet).
  • Fügen Sie das AfterBuild-Ziel hinzu, um die Guids in Components.wxs zurückzusetzen.
  • Überprüfen Sie mit Orca, ob jede Komponente in jedem MSI die geänderte Guid aufweist.
  • Überprüfen Sie, dass die Original-Guids wiederhergestellt sind.
  • Überprüfen Sie, dass jedes MSI das richtige Produkt und den richtigen Speicherort installiert (und aktualisiert).

Beispiel Config.wxi

Beispiel Config.Common.wxi

Beispiel Components.wxs

          ...

Hinweis: Ich würde jetzt vorschlagen, das Guid-Attribut aus dem Komponenten (entspricht *) auszulassen, eine Datei pro Komponente zu verwenden und die Datei als Schlüsselpfad festzulegen. Dadurch entfällt die Notwendigkeit, die Ziele ModifyComponentsGuids und RevertComponentsGuids wie unten gezeigt aufzurufen. Dies ist möglicherweise nicht für alle Ihre Komponenten möglich.

Beispiel Setup.Live.wixproj

Abschließende Gedanken

  • Dieser Prozess sollte auch für die Erstellung unterschiedlicher Installer für verschiedene Merge-Module (Live, Test, ... als Features) für denselben Installer funktionieren. Ich habe mich für verschiedene Installer entschieden, da dies sicherer erschien. Es besteht mehr Risiko, dass jemand Live anstelle von Schulung aktualisiert, wenn sie sich auf demselben PC befinden und Sie nur Features für die verschiedenen Merge-Module verwenden.
  • Wenn Sie Ihr MSI verwenden, um Upgrades sowie neue Installationen durchzuführen, d.h. den Ansatz mit nur einem Major-Upgrade, und Ihren Installationsort in der Registrierung speichern, denken Sie daran, eine Variable für den Schlüsselnamen für jede Installation zu erstellen.
  • Wir erstellen auch Variablen in jedem Config.wxi, um eindeutige virtuelle Verzeichnisnamen, Anwendungspools, Datenbanknamen usw. für jeden Installer zu ermöglichen.

UPDATE 1: Das automatische Generieren von Komponenten-Guids macht den Aufruf der FileUpdate-Aufgabe überflüssig, wenn Sie für jede Datei eine Komponente mit Guid="*" erstellen und die Datei als Schlüsselpfad festlegen.

UPDATE 2: Eines der Probleme, mit denen wir konfrontiert waren, ist, dass bei manuellem Löschen der temporären Dateien gelöscht werden müssen, wenn der Build fehlschlägt, wenn Sie Ihre Komponenten-Guids nicht automatisch generieren.

UPDATE 3: Es wurde eine Möglichkeit gefunden, die Abhängigkeit von svn:externals und die temporäre Dateierstellung zu entfernen. Dies macht den Build-Prozess widerstandsfähiger (und ist die beste Option, wenn Sie Ihre Guids nicht mit Wildcards versehen können) und weniger brüchig, wenn ein Build-Fehler in light oder candle auftritt.

UPDATE 4: Unterstützung für Multiple Instances mit Instanztransformationen ist in WiX 3.0+ verfügbar, auf jeden Fall einen Blick wert.

0 Stimmen

+1 für die MSBuild Community Tasks-Referenz, liebe dieses Paket.

17voto

Terrance Punkte 11609

Verwendung des Msi-Diagnoseloggings, um detaillierte Fehlerinformationen zu erhalten

msiexec /i Package.msi /l*v c:\Package.log

Wo

Package.msider Name Ihres Pakets ist und    c:\\Package.logist, wo Sie die Ausgabe des Protokolls möchten

Msi-Fehlercodes

Wix-Einführungsvideo
Oh und zufälliges Wix-Einführungsvideo mit "Mr. WiX" Rob Mensching ist "konzeptuell hilfreich."

2 Stimmen

+1 Es wäre viel besser, wenn wir das Protokollieren direkt von Wix aus aktivieren könnten, anstatt über die Befehlszeile.

3 Stimmen

WiX tut. Legen Sie die MsiLogging-Eigenschaft fest. Nur unterstützt von Windows Installer 4.0+.

0 Stimmen

Vielen Dank, "Herr Wix". Muss das überprüfen.

17voto

Cheeso Punkte 184210

Verwenden Sie Javascript-CustomActions, weil sie soooo einfach sind

Manche Leute haben gesagt, dass Javascript das falsche Werkzeug für MSI CustomActions ist. Gründe dafür sind: schwer zu debuggen, schwer zuverlässig zu machen. Ich stimme dem nicht zu. Es ist nicht schwer zu debuggen, sicherlich nicht schwieriger als C++. Es ist einfach anders. Ich fand das Schreiben von CustomActions in Javascript super einfach, viel einfacher als mit C++. Viel schneller. Und genauso zuverlässig.

Es gibt nur einen Nachteil: Javascript CustomActions können mit Orca extrahiert werden, während eine C/C++-CA Reverse-Engineering erfordern würde. Wenn Sie möchten, dass Ihr Installationsprogramm als geistiges Eigentum geschützt ist, sollten Sie Skripten ausweichen.

Wenn Sie Skript verwenden, müssen Sie nur mit einer Struktur beginnen. Hier ist etwas, um Ihnen den Einstieg zu erleichtern.


Javascript-"Boilerplate"-Code für CustomAction:

//
// CustomActions.js 
// 
// Vorlage für WIX-Custom Actions in Javascript geschrieben.
// 
// 
// Mon, 23. Nov 2009  10:54
// 
// ===================================================================

// http://msdn.microsoft.com/en-us/library/sfw6660x(VS.85).aspx
var Buttons = {
        OkOnly           : 0,
        OkCancel         : 1,
        AbortRetryIgnore : 2,
        YesNoCancel      : 3
};

var Icons = {
        Critical         : 16,
        Question         : 32,
        Exclamation      : 48,
        Information      : 64
};

var MsgKind = {
        Error            : 0x01000000,
        Warning          : 0x02000000,
        User             : 0x03000000,
        Log              : 0x04000000
};

// http://msdn.microsoft.com/en-us/library/aa371254(VS.85).aspx
var MsiActionStatus = {
        None             : 0,
        Ok               : 1, // Erfolg
        Cancel           : 2,
        Abort            : 3,
        Retry            : 4, // auch suspend genannt?
        Ignore           : 5  // überspringt restliche Maßnahmen; das ist kein Fehler.
};

function MyCustomActionInJavascript_CA() {
    try {
        LogMessage("Hallo von MyCustomActionInJavascript");
        // ...hier arbeiten...
        LogMessage("Auf Wiedersehen von MyCustomActionInJavascript");
    }
    catch (exc1) {
        Session.Property("CA_EXCEPTION") = exc1.message ;
        LogException(exc1);
        return MsiActionStatus.Abort;
    }
    return MsiActionStatus.Ok;
}

// Zeigt eine MessageBox an. Schreibt auch eine Nachricht ins MSI-Protokoll, wenn es aktiviert ist. 
function LogException(exc) {
    var record = Session.Installer.CreateRecord(0);
    record.StringData(0) = "CustomAction: Ausnahme: 0x" + decimalToHexString(exc.number) + " : " + exc.message;
    Session.Message(MsgKind.Error + Icons.Critical + Buttons.btnOkOnly, record);
}

// Schreibt eine Informationsnachricht ins MSI-Protokoll, wenn es aktiviert ist. 
function LogMessage(msg) {
    var record = Session.Installer.CreateRecord(0);
    record.StringData(0) = "CustomAction:: " + msg;
    Session.Message(MsgKind.Log, record);
}

// http://msdn.microsoft.com/en-us/library/d5fk67ky(VS.85).aspx
var WindowStyle = {
    Hidden : 0,
    Minimized : 1,
    Maximized : 2
};

// http://msdn.microsoft.com/en-us/library/314cz14s(v=VS.85).aspx
var OpenMode = {
    ForReading : 1,
    ForWriting : 2,
    ForAppending : 8
};

// http://msdn.microsoft.com/en-us/library/a72y2t1c(v=VS.85).aspx
var SpecialFolders = {
    WindowsFolder : 0, 
    SystemFolder :  1, 
    TemporaryFolder : 2
};

// Führt einen Befehl über cmd.exe innerhalb des MSI aus
function RunCmd(command)
{
    var wshell = new ActiveXObject("WScript.Shell");
    var fso = new ActiveXObject("Scripting.FileSystemObject");
    var tmpdir = fso.GetSpecialFolder(SpecialFolders.TemporaryFolder);
    var tmpFileName = fso.BuildPath(tmpdir, fso.GetTempName());

    LogMessage("shell.Run("+command+")");

    // Verwende cmd.exe, um die Ausgabe umzuleiten
    var rc = wshell.Run("%comspec% /c " + command + "> " + tmpFileName, WindowStyle.Hidden, true);
    LogMessage("shell.Run rc = "  + rc);

    // hier optional die Ausgabe des Befehls parsen 
    if (parseOutput) {
        var textStream = fso.OpenTextFile(tmpFileName, OpenMode.ForReading);
        while (!textStream.AtEndOfStream) {
            var oneLine = textStream.ReadLine();
            var line = ParseOneLine(oneLine);
                ...
        }
        textStream.Close();
    }

    if (deleteOutput) {
        fso.DeleteFile(tmpFileName);
    }

    return {
        rc : rc,
        outputfile : (deleteOutput) ? null : tmpFileName
    };
}

Registrieren Sie dann die benutzerdefinierte Aktion mit etwas Ähnlichem:


Sie können natürlich beliebig viele Javascript-Funktionen einfügen, für mehrere benutzerdefinierte Aktionen. Ein Beispiel: Ich habe Javascript verwendet, um eine WMI-Abfrage auf IIS auszuführen, um eine Liste vorhandener Websites zu erhalten, an die ein ISAPI-Filter installiert werden könnte. Diese Liste wurde dann verwendet, um später in der UI-Sequenz ein Listenfeld zu bevölkern. Alles ganz einfach.

Bei IIS7 gibt es keinen WMI-Anbieter für IIS, daher habe ich den Ansatz shell.Run() verwendet, um appcmd.exe aufzurufen und die Arbeit auszuführen. Einfach.

Zugehörige Frage: Über Javascript CustomActions

2 Stimmen

+1 Ich finde den DTF-Ansatz einfach einzurichten, aber JavaScript könnte auch nützlich sein.

12voto

Terrance Punkte 11609

Mit Heat.exe Gesicht zertrümmern und "Epic Pwnage" bei schmerzhaft großen Installationen verursachen

Erweiterung zu den Antworten von Si und Robert-P über heat.

Übersetzung: (Mit heat, um das manuelle Eingeben von einzelnen Dateien in das Projekt zu vermeiden und für die Automatisierung von Builds für einen insgesamt einfacheren Prozess.)

WiX 2.0 Heat Syntax ausführlich

Für neuere Versionen (nicht so unterschiedlich von älteren Versionen, aber es gibt potenziell nervige Syntaxänderungen....) gehe in das Verzeichnis, in dem Heat ist, von der cmd.exe aus und gib einfach heat ein, aber ich habe hier ein Beispiel für Hilfe bei neueren Versionen.

Füge folgendes deinen Build-Ereignissen in Visual Studio 2010 hinzu.
(Projekt mit der rechten Maustaste anklicken->Eigenschaften ->Build-Ereignisse-> Vor-Build-Ereignisse)

$(WIX)bin\heat.exe" dir "$(EnviromentVariable)" -cg GroupVariable -gg -scom -sreg -sfrag - srd -dr INSTALLLOCATION -var env.LogicPath -out "$(FragmentDir)\FileName.wxs

\-gg 

Generiert GUIDs, wenn Heat ausgeführt wird (also wenn du das obige Kommando ausführst)

\-scom 

Keine "COM-Dateien" erfassen

\-sreg 

Keine "Registrierungsdateien" erfassen

\-sfrag 

Keine "Fragments" erfassen

\-srd 

Kein "Stammverzeichnis" erfassen

dir

dir zeigt an, dass Heat in einem Ordner suchen soll

"$(EnviromentVariable)"

Der Name der Variablen, die du den Präprozessorvariablen in den (Rechtsklick auf Projekt, Gehe zu Eigenschaften) Projekt-Eigenschaften->Build-Bereich hinzufügen würdest, wo es heißt Definiere Präprozessorvariablen (unter der Annahme von Visual Studio 2010)

Beispiel:
EnviromentVariable=C:\\Project\\bin\\Debug;Keine doppelten Anführungszeichen, sondern mit einem Semikolon enden

\-cg GroupVariable 

Die ComponentGroup, auf die von dem erstellten Fragment auf die Haupt-WXS-Datei verwiesen wird

FragmentDir

Das Fragment-Verzeichnis, in dem das Ausgabewxs-Fragment gespeichert wird

FileName.wxs

Der Name der Datei

Ganzer Tutorial hier, so verdammt hilfreich

Teil 1 Teil 2

0 Stimmen

Es gibt ein weiteres nützliches Werkzeug für etwas andere Zwecke: Paraffin (wintellect.com/CS/blogs/jrobbins/archive/2010/03/10/4107.as‌​px)

12voto

Ich bin überrascht, dass noch niemand erwähnt hat, T4 während des Builds zu verwenden, um die WXS-Datei zu generieren. Dies habe ich von Henry Lee @ New Age Solutions gelernt.

Im Wesentlichen erstellen Sie eine benutzerdefinierte MSBuild-Aufgabe, um eine T4-Vorlage auszuführen, und diese Vorlage gibt die WXS-Datei kurz vor dem Kompilieren des Wix-Projekts aus. Dies ermöglicht es Ihnen (je nach Implementierung), automatisch alle aus einer anderen Lösung kompilierten Assemblys einzuschließen (was bedeutet, dass Sie die wxs nicht mehr jedes Mal bearbeiten müssen, wenn Sie eine neue Assembly hinzufügen).

2 Stimmen

+1 das ist wirklich nett, ich mache mir nicht so viele Sorgen um Assemblys, aber unsere Webprojekte können Probleme mit aspx-Seiten und anderen Artefakten (Bilder, CSS) haben, die dem Projekt hinzugefügt werden, aber nicht zu WiX gehören.

4 Stimmen

Für zukünftige Besucher hat Wix 3.5 ein Dienstprogramm heat.exe, das diese Ernte automatisch durchführt.

0 Stimmen

@Mrchief - Ich glaube nicht, dass Heat lokal kopierte Referenzassemblys erkennt - dies ist anscheinend für Version 4.0 geplant. Referenz: sourceforge.net/tracker/…

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X