Créer un setup VSTO intelligemment

L’autre jour, je me rendais chez un client pour compléter deux de ses addins VSTO pour Outlook et c’est quand j’ai posé des questions quant au mode de déploiement désiré que j’ai été quelque peu étonné par les solutions actuellement utilisées.

  • Le premier projet était déployé en copiant les binaires du projet sur chaque machine et en lançant à la main le fichier monprojet.vsto. Old school mais efficace!
  • Le second était un projet de setup standard, bien configuré comme il faut avec les clés registres, les propriétés du setup dûment remplies et les fichiers étaient chargés automatiquement sur la sortie du projet d’addin.

Malheureusement, aucune des solutions n’était satisfaisante et nous allons voir pourquoi cela.

Afin de comprendre le pourquoi de ce billet, plaçons-nous dans le contexte d’un addin VSTO. Pour cela, créons un projet d’addin Outlook que l’on nommera MonAddinOutlook. À la solution du projet, ajoutons maintenant un projet de Setup, nommé MonAddinOutlook.Setup.

Avec Visual Studio 2010, contrairement aux anciens projets de setup, il n’est plus nécessaire d’ajouter les fichiers à la main ; il est possible de spécifier de récupérer les fichiers générés d’un autre projet, et ce, de façon dynamique, ce qui signifie qu’au fur et à mesure des évolutions du projet les nouveaux fichiers seront automatiquement ajoutés au setup sans aucune action utilisateur. Pour cela, sur votre projet, cliquez à l’aide du bouton droit et choisissez Add > Project Output...

Dans la fenêtre qui s’ouvre, sélectionnez dans la liste déroulante le projet d’addin VSTO et choisissez Primary Output dans la liste des choix possibles, comme le montre la capture suivante :

image

Le projet Setup va alors analyser les fichiers pour détecter les références à insérer et les ajouter dans Detected Dependencies.

Avec ce paramétrage, chaque fois que vous ferez évoluer votre projet, générer de nouveaux fichiers de sortie, ceux-ci seront automatiquement ajoutés au package d’installation. Ceci serait la solution idéale pour la plupart des types de projets... mais pas pour un projet VSTO.

La problématique de ce paramétrage est qu’il va copier les fichiers *.exe et *.dll générés, mais pas les fichiers *.manifest ou *.vsto que nécessitera votre addin pour être fonctionnel une fois déployé.

La solution

Il vous suffit de cliquer à l’aide du bouton droit sur le projet de setup, de choisir Add > File... dans le menu contextuel et d’aller dans le répertoire bin/release pour sélectionner les fichiers vsto et manifest générés.

Compilez alors le projet de setup pour voir votre installeur prêt et fini. Sauf que voilà, votre projet de setup est devenu obsolète à la même seconde. Il vous faut alors comprendre le principe du fichier manifest qui sert à valider la signature (par hash) des fichiers de votre projet VSTO.

Si vous éditez une ligne de code de votre projet ou rajoutez des fichiers à votre projet et recompilez le projet d’addin et le projet de setup, à la prochaine installation, un message d’erreur vous indiquera que le manifest n’est pas correct par rapport à la version déployée (« ...has a different computed hash than specified in manifest »). Il est nécessaire à chaque compilation du projet de recopier le fichier vsto et le fichier manifest dans le projet de setup.

La meilleure solution

L’adage dit qu’un bon développeur est un développeur fainéant et surtout, un développeur n’est jamais à l’abri d’une erreur et personne n’a envie de livrer un setup qui serait finalement faillible. La solution consiste donc à automatiser tout cela et cela impose de passer par les post-build events, ces commandes lancées automatiquement à la fin de la compilation d’un projet.

Il nous faut écrire une commande qui copie les fichiers vsto et manifest générés dans le projet de setup. Nous pourrions le faire directement ou alors passer par un troisième projet qui servira de conteneur et dans le lequel nous pourrons placer des classes supplémentaires si un jour il est nécessaire de faire une classe personnalisée dédiée à l’installation.

1— préparation du projet helper

Créez un nouveau projet de type Bibliothèque de classe que vous nommerez MonAddinOutlook.SetupHelper. De ce projet, supprimez le fichier class1.cs et ajoutez les fichiers manifest et vsto du répertoire bin/Release du projet d’addin. Pour chacun de ces deux fichiers, allez dans les propriétés (F4) et mettez leur mode de compilation en Content

image

2— ajout des commandes post-build

Allez ensuite dans les propriétés de votre projet d’addin, dans l’onglet Build Events, et dans la textbox dédiée au post-build event, ajoutez les lignes suivantes :

copy $(TargetDir)$(TargetName).vsto $(SolutionDir)MonAddinOutlook.$(ProjectName).SetupHelper\$(TargetName).vsto
copy $(TargetDir)$(TargetFileName).manifest $(SolutionDir)MonAddinOutlook.$(ProjectName).SetupHelper\$(TargetFileName).manifest

image

3— configuration du projet de setup

Pour finir, nous allons dire à notre projet setup d’aller récupérer les fichiers du projet Helper. Pour cela, sur le projet de déploiement, cliquez à l’aide du bouton droit et choisissez Add > Projet Output...

Cette fois-ci, sélectionnez le projet MonAddinOutlook.SetupHelper dans la liste déroulante puis cliquez sur ContentFiles. Cela aura pour effet de récupérer uniquement les fichiers avec l’option Build Action = Content, c’est-à-dire les deux fichiers vsto et manifest.

Au final, votre solution devrait ressembler à la capture suivante.

image

Vous voilà parés d’un projet de setup à l’épreuve des balles et qui sera valable sans modifications au fil des évolutions de votre addin.

Néanmoins, d’autres sources peuvent causer des erreurs lors du déploiement de votre addin, et pour cela, rien de mieux que la KB de la MSDN.