Loupe

Custom Action WiX en C# : Introduction

Introduction WiX

À l’ère du déploiement continu, automatiser l’installation de ses applications n’est plus seulement une nécessité, c’est devenu un prérequis.

Si dans de nombreuses situations standards, quelques copies de fichiers agrémentées de simples scripts (PowerShell ?) suffisent, il n’est pas rare que la création d’un installeur de type .msi soit envisagée, ne serait-ce que pour proposer une interface graphique à l’installation, s’intégrer plus facilement dans les systèmes de déploiement de logiciels dans des parcs informatiques, etc.

Parmi toutes les technologies de génération d’installeurs .msi disponibles à l’heure actuelle dans l’univers Microsoft, on en retient principalement 2 :

  • InstallShield (http://www.installshield.fr/), système propriétaire de Flexera, disponible en version gratuite et téléchargeable directement depuis Visual Studio… jusqu’à la version 2015 (Pas de version gratuite pour Visual Studio 2017 prévue à ce jour)
  • WiX pour Windows installer XML toolset (http://wixtoolset.org/), logiciel libre basé sur des fichiers XML, offrant également une très bonne intégration à Visual Studio

Peu importe la technologie choisie, dès lors que l’installation dépasse la simple « copie de fichiers », il est très rapidement nécessaire de se tourner vers la création d’une « Custom Action » qui permettra l’exécution d’un script, d’un exécutable, voire même d’une librairie C#.

Création d’une Custom Action WiX en C#

Pour des raisons d’efficacité (langage C# bien connu des équipes .NET) et maintenabilité (facilité de création de tests d’intégrations voire tests unitaires sur cette librairie), la Custom Action WiX en C# est une solution de choix lorsqu’il s’agit d’étendre les possibilités des installeurs WiX.

La documentation officielle étant encore à l’heure actuelle peu évidente à appréhender, nous allons voir dans la suite de cet article comment mettre en place facilement une Custom Action WiX.

Choix de l’équipement (Prérequis)

Pour démarrer, 2 éléments sont nécessaires (http://wixtoolset.org/releases/):

  • La dernière version stable de WiX (version 3.11 lors de l’écriture de cet article)
  • L’extension correspondant à votre version de Visual Studio (version 2017 dans les captures d’écran de cet article)

00-installation-wix-visual-studio.PNG

Création de la Custom Action WiX dans Visual Studio

L'installation de l'extension pour Visual Studio permet de rajouter un Template de projet de création de Custom Action pour WiX. Ce projet sous forme de librairie C# devra être ensuite référencée dans le projet d’installation WiX (à créer si cela n'est pas encore fait)

02-creation-projet-custom-action.PNG

Par défaut, un fichier CustomAction.cs est créé et contient une classe contenant une méthode, elle-même décorée par un attribut [CustomAction] qui permet à l’installeur WiX de reconnaître et d’exécuter cette méthode.

03-ajout-parametre-custom-action-wix.PNG

Dans cet exemple, 2 modifications ont été effectuées :

  • La récupération d'un paramètre, fourni par l'installeur à l’exécution
CustomActionData data = session.CustomActionData;
  • L’écriture de la valeur de ce paramètre dans le log d'installation
session.Log($"Hello { data["Name"] }");

Note : Dans cet exemple, la Custom Action sera exécutée en mode « deferred » et nécessite de passer par la propriété CustomActionData pour accéder aux paramètres fournis. Dans le cas d'une Custom Action exécutée en mode « immediate », la récupération d'un paramètre s’effectue de la manière suivante :

session["name"]

Ajout de la référence vers la Custom Action WiX

Ne pas oublier de référencer le projet contenant la CustomAction depuis le projet d'installation WiX :

04-reference-project-custom-action-wix.PNG

Il est ensuite nécessaire de rajouter plusieurs éléments XML au fichier Product.wxs décrivant le déroulement de l'installation de l'application

05-reference-custom-action-product-wxs-wix.PNG

<CustomAction Id="SayHello" BinaryKey="MaCustomAction.CA" DllEntry="DeferredHello" Execute="deferred" Return="check" Impersonate="no" />

<Property Id="SayHello" Value="Name=World" />

<Binary Id="MaCustomAction.CA" SourceFile="..\MaCustomAction\bin\Debug\MaCustomAction.CA.dll" />

<InstallExecuteSequence>
  <Custom Action="SayHello" After="InstallFiles">NOT Installed</Custom>
</InstallExecuteSequence>

La balise <CustomAction> permet de configurer l'exécution de la Custom Action, notamment :

  • Id : Id de la Custom Action
  • BinaryKey : Id de la balise <Binary> qui définit le binaire à exécuter
  • DllEntry : Le nom de la méthode à exécuter
  • Execute : Le mode d'exécution (deferred, immediate, etc.)
  • Return : Est-ce que le retour d'exécution de la Custom Action doit être pris en compte ou non durant l'installation
  • Impersonate : Est-ce que le contexte d'exécution de l'utilisateur qui exécute l'installeur doit être reproduit (notamment la vérification des permissions), ou est-ce que le compte LocalSystem doit être utilisé (ce qui donne accès à des privilèges élevés)

La balise <Property> permet de passer en paramètre des valeurs à la Custom Action, ses attributs sont :

  • Id : /!\ Attention /!\ : Son Id doit être identique à l'Id de la Custom Action
  • Value : Contient les paramètres, au format NOM_PARAMETRE=VALEUR_PARAMETRE

La balise <Binary> permet de préciser le chemin de la librairie C# à utiliser :

  • Id : /!\ Attention /!\ : Son Id doit être identique à la valeur de la propriété BinaryKey de la Custom Action
  • SourceFile : Chemin de la librairie (.dll) à utiliser

La balise <InstallExecuteSequence> permet de préciser l'ordre d'exécution, notamment des Custom Actions. Elle contient des balises <Custom> dont les attributs sont :

  • Action : /!\ Attention /!\ : Sa valeur doit être identique à l'Id de la Custom Action
  • After/Before : Permet de définir que la Custom Action doit s'exécuter avant / après un évènement d'installation particulier tel que InstallInitialize / InstallFinalize, InstallFiles, etc.
  • Value : la valeur de la balise <Custom> permet de préciser dans quels cas la Custom Action doit s'exécuter. "NOT Installed" permet de préciser que l'action doit s'exécuter lors de l'installation

Une fois ces balises ajoutées, le projet WiX devrait produire un msi capable d'exécuter la Custom Action. Félicitations !

Visualiser l’exécution de la Custom Action WiX dans les logs d’installation

Pour vérifier que la Custom Action ainsi créée s'exécute bien, il suffit de produire le fichier de log d'installation, et de vérifier l'output renvoyé par la Custom Action.

Pour cela, il suffit d'exécuter msiexec.exe avec les paramètres suivants :

  • /i : pour préciser l'installation (Note : /x permet la désinstallation)
  • NOM_MSI : Le nom du MSI à installer
  • /l*v NOM_FICHIER : permet de préciser que le log de l'installation doit être redirigé dans un fichier nommé NOM_FICHIER

06-installation-msi-avec-log.PNG

Une fois l'installation terminée, vérifiez dans le fichier de log que la Custom Action s'effectue bien en recherchant "Calling custom action" dans le fichier de log produit

07-log-custom-action-wix-ed.PNG

Conclusion

Créer un installeur personnalisé n'est clairement pas trivial. Si WiX permet de simplifier cette tâche, il nécessite cependant pas mal de montée en compétence sur des options pas toujours très bien documentées.

C'est pourquoi la possibilité de créer une extension C#, exécutable depuis l'installeur WiX, rend la personnalisation d'un installeur plus accessible aux développeurs .NET (et permet en plus de rajouter facilement des tests automatisés 😊)

La solution d'exemple utilisée dans cet article est disponible à cette adresse :

https://github.com/vfabing/wix-custom-action-sample

Note : Ajouter un fichier minimum à déployer

Pour qu'un msi exécute une Custom Action, il est nécessaire qu'il y ait au moins un fichier à déployer. Si vous suivez cet article à partir d'un nouveau wixproj, il est nécessaire de rajouter un fichier TextFile1.txt dans le wixproj, et rajouter les balises <Component> et <File> comme dans l'exemple suivant :

AA-referencer-un-fichier-a-deployer.PNG

<Component>
  <File Source="TextFile1.txt" />
</Component>

 

Photo de profil

Ces billets pourraient aussi vous intéresser

Vous nous direz ?!

Commentaires

comments powered by Disqus