Accueil > .Net, Développement, WIX > How to Start : WIX

How to Start : WIX

C’est un peu le genre d’article que j’aurais aimé trouvé.
Pour résumé, j’ai travaillé sur WIX, il y a peut.
Si la documentation est assez impressionnante, il y a un petit truc sympa que j’aurais aimé trouvé plus aisément : un guide pour mettre en place un truc simple. Un genre de « Hello World » pour WIX.

Donc, comme j’ai pas trouvé, je le fais !
Ça sera probablement un peu brouillon, sans doute incomplet, mais ça correspond à ma découverte de WIX.

 

Qu’est ce que WIX ?

 
WIX pour Windows Installer XML.
Le site central de WIX est disponible est assez touffu en informations : WIX Toolset (en), avec une documentation disponible (en) et un nombre pas croyable de tutoriaux (en).
Par contre, pour des « How To », la page pointe pour le moment vers une 404…

Il y a également un billet MSDN qui peut être utile : Automatisation des versions avec MSBuild et Windows Installer XML.

Bref, beaucoup de choses, mais parfois, c’est quand même un peu trop.
Quand il y a trop de choix, c’est parfois un peu compliqué de savoir par quel bout prendre la chose…

 

Pré-requis

 

Déjà, il faut installer WIX.
Je vais utiliser ici la version 3.6, mais une version 3.7 est disponible depuis la page Codeplex du projet WIX.
Avant de l’installer, il est bon de fermer Visual Studio puisqu’un nouveau template de projet va être installé.

Et…c’est tout.

 

Solution de test

 

Le scénario que je vais utiliser ici est relativement simple et permettra, entre autres, déborder plusieurs points.
C’est une application WCF hébergée par un Service Windows qui va être utilisée par un client (une application console).
La partie service va donc être installée via WIX, la partie cliente ne servant qu’à valider que tout s’est bien installé.

Dans ce cadre, je vais avoir 4 projets (csproj) :

  • SamplesWIX.Core : la bibliothèque de classe qui va gérer la logique du service
  • SamplesWIX.Host : le projet console contenant Service Windows
  • SamplesWIX.Client : l’application console qui servira de client
  • SamplesWIX.Setup : le projet WIX qui va générer un fichier *.msi

Pour le projet WIX, il est disponible ici :
WIX - Projet Visual Studio

 

La logique du Service Windows

 

Déjà, on va commencer par référencer l’assembly « System.ServiceModel », WCF oblige, dans le projet SamplesWIX.Core.
Comme c’est pour une démo, on va rester très simple :

// IMessageContract.cs
namespace SamplesWIX.Core
{
    using System.ServiceModel;

    [ServiceContract]
    public interface IMessageContract
    {
        [OperationContract]
        string ShowWelcomeMessage(string name);
    }
}

// MessageService .cs
namespace SamplesWIX.Core
{
    public class MessageService : IMessageContract
    {
        public string ShowWelcomeMessage(string name)
        {
            return string.Format("Bienvenue, {0} !", name);
        }
    }
}

 

Le Service Windows

 

Maintenant, allons dans le projet SamplesWIX.Host.
Première étape, référencer le projet SamplesWIX.Core ainsi que l’assembly « System.ServiceModel ».

On va donc créer deux fichiers :

  • Un « Service Windows » nommé MessageHost.cs
  • Un « Classe Installer » nommé MessageInstaller.cs

On va mettre plein de choses en dur, mais c’est pour aller vers la simplicité.
Ce n’est donc absolument pas du code à mettre en production !

// MessageHost.cs
namespace SamplesWIX.Host
{
    using System;
    using System.ServiceModel;
    using System.ServiceModel.Description;
    using System.ServiceProcess;
    using SamplesWIX.Core;

    public partial class MessageHost : ServiceBase
    {
        private ServiceHost svcHost = null;

        public MessageHost()
        {
            InitializeComponent();
        }

        protected override void OnStart(string[] args)
        {
            if (svcHost != null)
            {
                svcHost.Close();
            }

            string strAdrHTTP = "http://localhost:9001/MessageService";
            string strAdrTCP = "net.tcp://localhost:9002/MessageService";

            Uri[] adrbase = { new Uri(strAdrHTTP), new Uri(strAdrTCP) };
            svcHost = new ServiceHost(typeof(MessageService), adrbase);

            ServiceMetadataBehavior serviceBehavior = new ServiceMetadataBehavior();
            svcHost.Description.Behaviors.Add(serviceBehavior);

            BasicHttpBinding httpb = new BasicHttpBinding();
            svcHost.AddServiceEndpoint(typeof(IMessageContract), httpb, strAdrHTTP);
            svcHost.AddServiceEndpoint(
                typeof(IMetadataExchange),
                MetadataExchangeBindings.CreateMexHttpBinding(),
                "mex");

            NetTcpBinding tcpb = new NetTcpBinding();
            svcHost.AddServiceEndpoint(typeof(IMessageContract), tcpb, strAdrTCP);
            svcHost.AddServiceEndpoint(
                typeof(IMetadataExchange),
                MetadataExchangeBindings.CreateMexTcpBinding(), 
                "mex");

            svcHost.Open();
        }

        protected override void OnStop()
        {
            if (svcHost != null)
            {
                svcHost.Close();
                svcHost = null;
            }
        }
    }
}

// MessageInstaller .cs
namespace SamplesWIX.Host
{
    using System.ComponentModel;
    using System.Configuration.Install;
    using System.ServiceProcess;

    [RunInstaller(true)]
    public partial class MessageInstaller : Installer
    {
        private ServiceProcessInstaller process;
        private ServiceInstaller service;

        public MessageInstaller()
        {
            InitializeComponent();
            process = new ServiceProcessInstaller();
            process.Account = ServiceAccount.LocalSystem;
            service = new ServiceInstaller();
            service.ServiceName = "MessageService";
            service.DisplayName = "MessageService";
            service.Description = "WCF Launcher Hosted by Windows NT Service";
            service.StartType = ServiceStartMode.Automatic;
            Installers.Add(process);
            Installers.Add(service);
        }
    }
}

// Program.cs
namespace SamplesWIX.Host
{
    using System.ServiceProcess;

    public class Program
    {
        public static void Main()
        {
            ServiceBase[] servicesToRun;
            servicesToRun = new ServiceBase[] 
			{ 
				new MessageHost() 
			};
            ServiceBase.Run(servicesToRun);
        }
    }
}

 

Installeur WIX

 

Maintenant, passons dans le vif du sujet : l’installeur WIX.

 

Les références

 

WIX - Références
Il FAUT référencer TOUS les projets dont les assemblies devront être installées. Sinon, WIX ne va pas les trouver.

Ensuite, on va travailler sans aucune interface graphique, directement dans les fichiers XML. Miam ! ^^

 

Les types de fichiers WIX

 

Déjà, dans un projet WIX, il existe différents types de fichiers.

  • Le basique WiX File (*.wxs) qui va servir un peu à tout
  • WiX Include File (*wxi) qui va servir à stocker des variables ; attention, il faudra référencer ces fichiers de façon explicite !
  • WiX Localization File (*.wxl) qui va servir à localiser l’application
  • Text File (*.txt) assez évident…

Pour la localisation des fichiers, il faut connaître le LCID de la langue (je ferais un autre billet pour un petit utilitaire que je me suis fais, pour cette raison et d’autres).
Et dans ce cas, on aura un fichier *.msi par langue (à moins qu’il soit possible de changer la langue dans le wizard ?).
Pour en savoir plus sur la localisation, je suggère la lecture de ce billet : Creating localized MSI files using WiX toolset and .wxl files.

Il est possible de séparer les différents composants logiques par fichier *.wxs.
Par exemple l’interface du wizard, les composants devant être installés ou même l’installation d’un Service Windows…
Il y a donc de grandes chances que tous les *.wxs soient fusionnés à la compilation.

Dans notre cas, je vais créer quatre fichiers :

  • GlobalVariablesSettings.wxi : pour stocker la version du produit
  • Localization1036.wxl : pour gérer la localisation fr-fr
  • Product.wxs : pour gérer le produit (ce qui est installé)
  • UI.wxs : pour gérer l’IHM du wizard

 

Fichier GlobalVariablesSettings.wxi

 

<?xml version="1.0" encoding="utf-8"?>
<Include>
  <?define ProductVersion="0.0.0.1"?>
</Include>

Assez simple, il va juste contenir la version du MSI qui sera affichée dans « Programmes et fonctionnalités » de Windows.

 

Fichier Localization1036.wxl

 

<?xml version="1.0" encoding="utf-8"?>
<WixLocalization Culture="fr-fr" xmlns="http://schemas.microsoft.com/wix/2006/localization">
  <String Id="ProductName">Sample WIX - Démonstration</String>
  <String Id="Description">Sample WIX - Démonstration de l'installation via WIX d'un Service Windows hébergeant un service WCF.</String>
  <String Id="Keywords">WIX</String>
  <String Id="ProductFullName">Sample WIX</String>
  <String Id="CompanyName">kerrubin</String>
  <String Id="Language">1036</String>
  <String Id="ServiceName">Sample WIX - Service Windows</String>
  <String Id="UpgradeCode">{EADFAF52-3A67-4692-AB68-11358813C94F}</String>
  <String Id="DowngradeErrorMessage">Une version différente de Sample WIX est déjà installée, merci de la désinstaller au préalable.</String>
</WixLocalization>

Rien de bien compliqué non plus, ce sont juste des déclarations de variables.
A noter tout de même, la mention de la culture dans la balise WixLocalization.
Grâce à cela, le MSI sera généré dans le répertoire « bin\Release\fr-fr ».

 

Fichier Product.wxs

 

Je ne vais pas tout détailler, mais juste ce qui me parait réellement important.
Pour plus d’information, voir la documentation dont les liens sont fournis plus haut.

Dans un premier temps, référencer le fichier de variables globales :

  <?include GlobalVariablesSettings.wxi ?>

Ensuite, déclarer le produit (la ligne qui sera présente dans « Programmes et fonctionnalités »).

  <Product
    Id="????????-????-????-????-????????????"
    Name="$(loc.ProductName)"
    Language="$(loc.Language)"
    Version= "$(var.ProductVersion)"
    Manufacturer="$(loc.CompanyName)"
    UpgradeCode="$(loc.UpgradeCode)">
    <Package
      Id='????????-????-????-????-????????????'
      Manufacturer="$(loc.CompanyName)"
      InstallerVersion="200"
      Languages="$(loc.Language)"
      Compressed="yes"
      Comments="$(loc.Description)"
      Description="$(loc.Description)"
      Keywords="$(loc.Keywords)"
      InstallScope="perMachine" />

La balise Product n’est pas fermée car on va mettre d’autres choses dedans.

Quelques commentaires, pour ce morceau.
Il est possible d’accéder aux variables de localisation (fichiers *.wxl) via $(loc.VARIABLE) et aux variables (fichiers *.wxi) via $(var.VARIABLE).

Ensuite, tous les ID se basent sur des GUID. Mettre des ? à la place des chiffres va permettre de générer un GUID à la volée.
Par contre, le UpgradeCode est super important, c’est lui qui va identifier les MSI.
Pour rappel, dès que lorsqu’on lance un MÊME MSI pour la seconde fois (après installation, donc), il va demander si l’on veut réparer, modifier ou supprimer le produit. Par contre, si on lance un MSI différent (pour le même produit), alors il va nous envoyer bouler car les versions ne correspondent pas.
La version en question, c’est l’UpgradeCode. Il sera donc utile de modifier ce GUID pour chaque livraison.

En ayant cela en tête, il est possible de gérer ce cas via :

  <MajorUpgrade DowngradeErrorMessage="$(loc.DowngradeErrorMessage)" />

Ensuite, il faut spécifier la configuration du média, c’est à dire le MSI :

  <Media Id="1" CompressionLevel="high" Cabinet="$(loc.ProductName).cab" EmbedCab="yes" />

Dans ce cas, on indique que la compression est élevée, comment le fichier *.cab se nomme et surtout qu’il est embarqué dans le MSI.
Si la valeur est « no », alors le fichier sera placé à côté du MSI (et donc il ne faudra pas l’oublier pendant la livraison…).

Enfin, pour en finir avec la balsie Product, on va ajouter un élément permettant de dire ce qu’il faut installer.

    <Feature Id="ProductFeature" Title="SampleWIX.Setup" Level="1">
      <ComponentGroupRef Id="ProductComponents" />
    </Feature>
  </Product>

Ensuite, on va déclarer un Fragment pour spécifier les informations d’installation.

  <Fragment>
    <Property Id="WIXUI_INSTALLDIR" Value="INSTALLLOCATION" />

    <Directory Id="TARGETDIR" Name="SourceDir">
      <Directory Id="ProgramFilesFolder">
        <Directory Id="INSTALLLOCATION" Name="SampleWIX" />
      </Directory>
    </Directory>

    <UIRef Id="CustomWixUI" />
  </Fragment>

WIXUI_INSTALLDIR permet de spécifier où sera installer le produit.
Dans notre cas, c’est le wizard qui va le demander, donc on indique juste quelle variable sera utilisée.
Le TARGETDIR sera le chemin d’installation du produit.
Dans notre cas, le chemin par défaut sera ProgramFilesFolder (soit C:\Program Files (x86)\) suivit de SampleWIX.Setup (donc C:\Program Files (x86)\SampleWIX\).

L’UIRef permet de spécifier une interface créée à la main (dans le fichier UI.wxs, que nous verrons juste après).

Et pour finir, nous allons spécifier ce qui doit être installé.

  <Fragment>
    <ComponentGroup Id="ProductComponents" Directory="INSTALLLOCATION">
      <Component Id="ProductComponent" KeyPath="no" Guid="85D675E4-764B-4FBB-A2B0-5F3C49E71B72">

        <File
          Id='Host'
          Name='SamplesWIX.Host.exe'
          Source='$(var.SamplesWIX.Host.TargetDir)\SamplesWIX.Host.exe'
          Vital='yes' />

        <File
          Id='Core'
          Name='SamplesWIX.Core.dll'
          Source='$(var.SamplesWIX.Core.TargetDir)\SamplesWIX.Core.dll'
          Vital='yes' />

        <ServiceInstall
                Id="ServiceInstaller"
                Type="ownProcess"
                Vital="yes"
                Name="SamplesWIX.Host.exe"
                DisplayName="$(loc.ServiceName)"
                Description="$(loc.Description)"
                Start="auto"
                ErrorControl="normal"
                Interactive="no"
                Account="[ACCOUNT]"
                Password="[PASSWORD]"
              />
        <ServiceControl Id='ServiceControl' Name='SamplesWIX.Host.exe' Start='install' Stop='uninstall' Remove='uninstall' />
      </Component>
    </ComponentGroup>
  </Fragment>

Dans notre cas, il y a deux fichiers à installer : l’exécutable du service ainsi que l’assembly de WCF.
La variable $(var.SamplesWIX.Core.TargetDir) va chercher le chemin suivant le mode de compilation, donc le répertoire Debug ou Release, par exemple.
La déclaration est relativement simple.

Ensuite, il y a l’installation du service.
Alors, sur ce point, je ne suis pas très sûr. Tel que, il prend le premier fichier spécifié pour tenter de l’installer.
Je ne pas encore trouvé comment spécifier réellement le lien entre les fichiers (balises File) et le contenu de la balise ServiceInstall (même si les Name sont en cohérence).

Pour un Service Windows, il faut aussi spécifier le nom de compte et le mot de passe.
On ne va pas les mettre en dur, mais les demander à la personne qui installe le produit, via le wizard. D’où les variables.

Voilà. A ce stade, on a bien avancé, mais ça ne peut pas compiler puisqu’il manque quelque chose : « Unresolved reference to symbol ‘WixUI:CustomWixUI’ in section ‘Fragment:’. »

 

Fichier UI.wxs

 

Alors jusqu’à présent, c’était simple…
Mais là…

<?xml version="1.0" encoding="UTF-8"?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
  <Fragment>
    <UI Id="CustomWixUI">
      <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" />

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

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

      <Publish Dialog="InstallDirDlg" Control="Back" Event="NewDialog" Value="WelcomeDlg">1</Publish>
      <Publish Dialog="InstallDirDlg" Control="Next" Event="SetTargetPath" Value="[WIXUI_INSTALLDIR]" Order="1">1</Publish>
      <Publish Dialog="InstallDirDlg" Control="Next" Event="NewDialog" Value="ServiceAccountDlg" Order="2">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="ServiceAccountDlg" Control="Back" Event="NewDialog" Value="WelcomeDlg">1</Publish>
      <Publish Dialog="ServiceAccountDlg" Control="Next" Event="NewDialog" Value="VerifyReadyDlg">1</Publish>

      <Publish Dialog="VerifyReadyDlg" Control="Back" Event="NewDialog" Value="ServiceAccountDlg" Order="1">NOT Installed OR WixUI_InstallMode = "Change"</Publish>
      <Publish Dialog="VerifyReadyDlg" Control="Back" Event="NewDialog" Value="MaintenanceTypeDlg" Order="2">Installed</Publish>

      <Publish Dialog="MaintenanceWelcomeDlg" Control="Next" Event="NewDialog" Value="MaintenanceTypeDlg">1</Publish>

      <Publish Dialog="MaintenanceTypeDlg" Control="RepairButton" Event="NewDialog" Value="VerifyReadyDlg">1</Publish>
      <Publish Dialog="MaintenanceTypeDlg" Control="RemoveButton" Event="NewDialog" Value="VerifyReadyDlg">1</Publish>
      <Publish Dialog="MaintenanceTypeDlg" Control="Back" Event="NewDialog" Value="MaintenanceWelcomeDlg">1</Publish>

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

      <Dialog Id="ServiceAccountDlg" Width="370" Height="270" Title="[ProductName] Setup">
        <Control Id="Back" Type="PushButton" X="180" Y="243" Width="56" Height="17" Text="$(loc.BackButton)" />
        <Control Id="Next" Type="PushButton" X="236" Y="243" Width="56" Height="17" Default="yes" Text="$(loc.NextButton)">
          <Condition Action="disable"><![CDATA[ACCOUNT = "" OR PASSWORD = ""]]></Condition>
          <Condition Action="enable"><![CDATA[ACCOUNT <> "" AND PASSWORD <> ""]]></Condition>
        </Control>
        <Control Id="Cancel" Type="PushButton" X="304" Y="243" Width="56" Height="17" Cancel="yes" Text="$(loc.CancelButton)">
          <Publish Event="SpawnDialog" Value="CancelDlg">1</Publish>
        </Control>
        <Control Id="BannerBitmap" Type="Bitmap" X="0" Y="0" Width="370" Height="44" TabSkip="no" Text="WixUI_Bmp_Banner" />
        <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="Description" Type="Text" X="25" Y="23" Width="280" Height="15" Transparent="yes" NoPrefix="yes" Text="$(loc.DescriptionText)" />
        <Control Id="Title" Type="Text" X="15" Y="6" Width="200" Height="15" Transparent="yes" NoPrefix="yes" Text="{\WixUI_Font_Title}Service account" />      
        <Control Type="Text" Width="322" Height="26" X="25" Y="56" Id="BodyLabel" Text="$(loc.BodyLabelText)" NoPrefix="yes" />
        <Control Type="Text" Width="275" Height="10" X="25" Y="98" Id="AccountLabel" Text="$(loc.AccountLabelText)" />
        <Control Type="Edit" Width="194" Height="15" X="25" Y="111" Id="AccountTextbox" Property="ACCOUNT" />
        <Control Type="Text" Width="275" Height="10" X="25" Y="135" Id="PasswordLabel" Text="$(loc.PasswordLabelText)" />
        <Control Type="Edit" Width="194" Height="15" X="25" Y="148" Id="PasswordTextbox" Property="PASSWORD" Password="yes" />
      </Dialog>
    </UI>
  </Fragment>
</Wix>

Je vous ai fais peur ?
Si oui, c’est normal.
Si non…félicitations !😀

Déjà, on retrouve la balise Fragment qui indique un conteneur.
Puis la balise UI pour créer un élément du wizard dont le nom est « CustomWixUI » (que l’on retrouve dans le fichier précédent).

Les balises TextStyle et Property (les 4 premières) sont purement cosmétiques.

Viennent ensuite les DialogRef. Ce pavé représente les fenêtres par défaut à utiliser.
Ce sont des fenêtres déclarées dans WIX directement et que l’on peut réutiliser tel que, pour ne pas refaire tout le wizard.

Ensuite, on publie les différents éléments du wizard pour avoir une cinématique.
Ce n’est pas utile de les mettre dans l’ordre, puisque ce sont les attributs Dialog qui vont être utiliser pour les ordonner.
Mais dans cette étape, on doit spécifier les actions des boutons.

Prenons l’exemple suivant :

      <Publish Dialog="InstallDirDlg" Control="Next" Event="SetTargetPath" Value="[WIXUI_INSTALLDIR]" Order="1">1</Publish>
      <Publish Dialog="InstallDirDlg" Control="Next" Event="NewDialog" Value="ServiceAccountDlg" Order="2">1</Publish>

Ici, lorsque l’on est sur l’étape InstallDirDlg, on va avoir le bouton Next de présent.
Dès que l’on va cliquer dessus, deux actions seront réalisées.
La première est de récupérer le chemin spécifier dans le champ SetTargetPath pour le mettre dans la variable [WIXUI_INSTALLDIR] (que nous avons déjà rencontrés dans le fichier précédent).
La seconde va permettre de se rendre à la dialogue suivante qui va être ServiceAccountDlg.
L’attribut Order permet…d’ordonnancer les actions.

Et enfin, il y a le pavé Dialog qui permet de décrire la seule dialogue du wizard qui est customisée, à savoir : ServiceAccountDlg.
Lorsque l’on créé une nouvelle dialogue, il faut spécifier tous les composants qui vont apparaître et les placer à la main (Width, Height, X et Y).

A noter aussi, il est possible de conditionner l’accessibilité des boutons, c’est ce qui est fait sur le bouton Next : il faut que les variables ACCOUNT et PASSWORD soient alimentées.
Et ces variables sont alimentées d’après les champs de type Edit AccountTextbox et PasswordTextbox.

 

Installation

 

A cette étape, normalement, ça compile (ça marche chez moi😀 ).
Donc, il est possible de générer le MSI.

Après installation, dans « Programmes et fonctionnalités », on aura donc :
WIX - Programmes et fonctionnalités

Et sur les services :
WIX - Services

Et là, on remarquera donc que les valeurs entrées sur le service, autant pour son nom que pour ça description…eh bah, c’est pas celles-là !🙂
En gros, dans la partie MessageInstaller, c’est réellement pas la peine de s’embêter à alimenter les variables, mis à part si vous comptez l’installer via InstallUtil.

 

Le Client

 

A ce niveau, comme le Service Windows est installé, il est possible de l’attaquer en HTTP via l’URL qui a été spécifiée, à savoir « http://localhost:9001/MessageService &raquo;.
Et du coup, on peut ajouter une référence de service dans le client, ce qui va générer directement l’app.config.

Une fois ça, on fait un petit bout de code :

namespace SamplesWIX.Client
{
    using System;
    using SamplesWIX.Client.MessageServiceReference;

    public class Program
    {
        static MessageContractClient client = new MessageContractClient("BasicHttpBinding_IMessageContract");
        static void Main(string[] args)
        {
            CallService();
        }

        public static void CallService()
        {
            string input = Console.ReadLine();
            Console.WriteLine(client.ShowWelcomeMessage(input));
            CallService();
        }
    }
}

Et là, on lance l’application, on tape un nom et bam, ça fait des chocapics ! (ou pas)

 

Sources

 

La solution utilisée pour ce billet est disponible sur OneDrive.

 

Conclusion

 

Déjà, j’espère que ce (long) billet va être utile !🙂
Ensuite, WIX est assez puissant, voir même TRES puissant, mais il a l’inconvénient de son avantage : il est complexe.
Je suis loin de le maîtriser, mais pour un petit installeur sans grand prétention, c’est « assez simple » à gérer.

Après, dans ce billet, il y a aussi un service WCF hébergé par un Service Windows.
Là, même si c’est possible, je suis quand même un peu moins fan.
Je préfère les services WCF hébergé via IIS et attaquable en HTTP(s).
Avec Web Deploy, c’est d’une facilité enfantine à déployer, y compris et surtout, via des builds TFS.
Mais bon, ça dépend aussi beaucoup de l’usage du service WCF en question.

Catégories :.Net, Développement, WIX
  1. 24/03/2014 à 18:47

    Il faudra que je teste cette solution, depuis le temps que j’en entends parler … Surtout que depuis VS2012, il n’y a plus de projets Setup disponibles pour faire ses .MSI.
    Je trouve cela vraiment dommage !

    • 25/03/2014 à 09:50

      WiX est justement destiné à remplacer cet abandon.
      C’est plus puissant, plus « simple » (parfois) de faire les choses.
      Après, ce qu’il manque, ça pourrait être une IHM pour gérer tout ça.

  2. 30/04/2014 à 15:37

    Fabien, j’ai essayé de reprendre ton exemple, mais quelques infos sont manquantes je pense :
    Pour la partie UI, en effet, dans le csproj Wix Setup il faut ajouter des références WixUIExtension.dll.
    http://wixtoolset.org/documentation/manual/v3/wixui/wixui_dialog_library.html

    Mais peut être est-ce parce que depuis la solution a évoluée ?

  3. 30/04/2014 à 18:34

    C’est marqué sur l’image, sous « Installeur WIX » – « Les références »🙂

  4. Patrick
    19/06/2016 à 21:52

    Bonsoir,

    merci pour cette article.
    j’ai developpé un service WCF, avec un installer. Celui ci s’installe ( installUtil) et se lance correctement (net start/ GUI service).
    Malheureusement, malgré les divers tutoriaux que j’ai suivis, je n’arrive pas à installer ce service via un installer WiX.
    J’aurai aimer regarder vos sources, qui ne sont malheureusement plus disponibles.
    Pouvez vous les partager de nouveau ?

    merci de votre réponse.
    Patrick

  5. 20/06/2016 à 08:05

    Bonjour,

    J’ai mis à jour le lien OneDrive.

    J’avais déjà eu des problèmes lors de l’installation. C’était lié au compte utilisé.
    Pour vérifier, il suffit de virer les lignes

    Account= »[ACCOUNT] »
    Password= »[PASSWORD] »

    Dans Product.wxs et de rentrer des informations bidon dans le wizard.

    • Patrick
      20/06/2016 à 09:21

      Super !
      J’ai appliqué ton tuto (sans ) à mon projet et … génial !! j’ai bien mon service installé up & running, je me demande bien ce que j’ai pu loupé lors de mes essais precédents.

      j’ai laissé
      Account= »[ACCOUNT] »
      Password= »[PASSWORD] »
      et je n’ai pas eu de souci sur une machine « administrée », je verrai sur d’autres.
      (mes précedent essais malheureux avait Account= »LocalService »)

      Encore MERCI ! pour cet article🙂

  6. 20/06/2016 à 18:38

    Y a pas de quoi, ça me fait plaisir d’avoir un retour positif comme ça !🙂

  1. 30/10/2013 à 15:47
  2. 31/10/2013 à 21:17
  3. 21/03/2014 à 22:08

Laisser un commentaire

Entrez vos coordonnées ci-dessous ou cliquez sur une icône pour vous connecter:

Logo WordPress.com

Vous commentez à l'aide de votre compte WordPress.com. Déconnexion / Changer )

Image Twitter

Vous commentez à l'aide de votre compte Twitter. Déconnexion / Changer )

Photo Facebook

Vous commentez à l'aide de votre compte Facebook. Déconnexion / Changer )

Photo Google+

Vous commentez à l'aide de votre compte Google+. Déconnexion / Changer )

Connexion à %s

%d blogueurs aiment cette page :