Feb.02

[VS Extensibility] Part 1 : Comment étendre Microsoft Visual Studio

image La plupart des développeurs sur plateforme Microsoft/.NET ont bien l’habitude d’ouvrir leur Visual Studio pour le développement de leurs applications. Lancé en 1997, la 1ère version de Visual Studio (ou VS) nommé tout naturellement Visual Studio 97, a voulu réunir dans un seul et même IDE plusieurs langages qui étaient à l’époque le VB 5.0, VC++, InterDev, VJ++ et FoxPro. Depuis 2002 et l’arrivée de la plateforme .NET, Visual Studio est devenu l’IDE de référence permettant le développement d’application WinForm, ASP.NET (WebForm), Mobile, WPF, Services Web/WCF, workflow, etc… supportant plusieurs langages comme VB.NET, C#, VC++.net et bien d’ autre encore sous forme d’extension.

image La grande qualité de Visual Studio est sa capacité à être étendue pour l’enrichir de nouvelles fonctionnalités (Add-in), de nouveaux langages, designers (DSL), etc.. Dans la version 2008 il est aussi possible de se servir du Visual Studio Shell permettant l’utilisation du socle Visual Studio pour développer un IDE spécifique basé sur VS.

Au fil du temps, les API d’extensibilité de VS se sont de plus en plus ouvertes rendant plus accessible et plus facile le développement d’extension. Ouvrons donc notre Visual Studio 2008 pour y créer un nouveau projet ! Vous retrouverez quelques templates de projets d’extensibilité dont les principaux sont :image

  • VS Addin : pour créer un module/extension dans Visual Studio
  • VS Shell Isolated : pour créer un nouvel IDE basé sur Visual Studio
  • VS Language Package : pour ajouter un nouveau langage dans Visual Studio en spécifiant les analyseurs lexical/syntaxique, le compilateur, la coloration syntaxique pour le langage, etc…
  • VS Package : pour créer un package (visible dans le Splash screen de VS) contenant un ensemble d’éléments graphique, de services, de templates de projets, d’ éditeurs, ou encore de designers.
  • DSL : pour la création de designers dans Visual Studio

Dans cet article nous verrons comment créer un Add-in dans votre Visual Studio 2005 ou 2008 en parcourant les principales fonctionnalités que l’on voudra doter à notre Add-in (création de fenêtre, écriture dans les Window Pane, interaction avec la StatusBar ou Properties Window, etc…). Je mettrai aussi en avant les principaux problèmes et leur solutions que l’on rencontre couramment dans le développement de tel add-in.

Création du projet de type « VS Add-in » :

Commençons par créer un projet de type « Visual Studio Add-in » que nous nommerons « MonAddinDemo » ! Afin simplifier la création d’ un tel projet, Visual Studio vous lancera un assistant (wizzard) permettant de préparer votre projet de type Add-in :

image  image  image  image  image  image

  1. Choix du langage : ici en C#
  2. Choix de l’hôte qui chargera notre Add-in : ici nous créons un add-in compatible VS2005 et 2008 en mode normal et Macro (pour l’ édition de Macro)
  3. Choix du nom et description de notre Add-in
  4. Choix des options : ici nous sélectionnons le fait que nous voulons ajouter automatique notre add-in dans le menu Tools de VS.
  5. Choix des informations sur le « About »
  6. Résumé !

Une fois validée toutes les informations recueillies vont permettre à Visual Studio de créer votre projet d’ Add-in en personnalisant votre fichier .addin et Connect.cs en fonction des choix effectués dans l’ assistant.

Voici à quoi ressemble votre projet après création :

image

On y retrouve :

  • AssemblyInfo.cs : contenant les attributs sur notre assembly
  • CommandBar.resx : contenant les traductions des menus de niveau 1 (Fichier, Édition,  …) de Visual Studio dans toutes les cultures
  • Connect.cs : classe de démarrage de notre add-in (qui implémente IDTExtensibility2)
  • MonAddinDemo – For Testing.AddIn : contenant la description de l’ Add-in au format XML (pour le test !)
  • MonAddinDemo.Addin : idem mais pour le packaging !

Sans plus attendre, voyons ce que tout cela rend. Tapez F5 pour compiler et exécuter notre projet ! Une nouvelle instance de Visual Studio se lancera et en cliquant sur le menu Tools (ou Outils en français) nous retrouverons notre add-in avec une jolie icône 🙂

image

Fichiers .AddIn et la classe Connect – comment ca marche ?

Fichiers .AddIn

Les fichiers de type .AddIn sont en fait des fichiers XML de description d’un addin. Chaque addin a donc son fichier .AddIn permettant de le décrire en deux sections XML différentes : Les HostApplication(s) et la section Addin.

Les HostApplication(s) vont décrire quelles sont les applications qui hébergeront notre addin. Dans notre « MyAddinDemo » nous avons souhaité héberger notre addin au sein de VS 2005 (8.0) et 2008 (9.0) en mode normal et macro.

Le XML correspondant est donc :

image

La section Addin contiendra les propriétés de l’addin en question comme par exemple :

  • FriendlyName : Le nom de notre addin tel qu’il sera affiché dans le Gestionnaire d’Add-in de Visual Studio
  • Description : la description de notre addin.
  • AboutBoxDetail et AboutBoxIcon : les informations (détail et icône) pour la boite A Propos comme nous l’ avons spécifié dans l’ étape 5 de l’ assistant
  • Assembly : le fichier DLL de l’assembly .NET contenant notre addin
  • FullClassName : le nom complet de la classe Connect contenu dans notre Assembly (ici : MonAddinDemo.Connect)

Extrait de notre section Addin :

image

Au démarrage, Visual Studio parcourra les répertoire ci-dessous (plus de détails sur MZ-Tools) pour charger tous fichiers .AddIn qu’il trouvera.

  • %ALLUSERSPROFILE%\Application Data\Microsoft\MSEnvShared\AddIns
  • %VSCOMMONAPPDATA%\AddIns
  • %ALLUSERSDOCUMENTS%\Microsoft\MSEnvShared\AddIns (seulement pour VS 2008)
  • %APPDATA%\Microsoft\MSEnvShared\AddIns
  • %VSAPPDATA%\AddIns
  • %VSMYDOCUMENTS%\AddIns

Comme nous l’avons vu un peu plus haut, avec ces fichiers XML, Visual Studio sera capable de charger l’assembly et d’ instancier la classe de connexion (notre MonAddinDemo.Connect).

Vous avez remarqué la présence de deux fichiers .AddIn dans notre solution : un normal et un pour « testing ». En fait, un fichier <mon projet>.AddIn est créé pour décrire l’add-in tel que l’on utilisera lors du packaging. Le 2ème « For Testing » est en fait un raccourci vers un fichier .AddIn présent dans le répertoire « %VSMYDOCUMENTS%\AddIns« . Il permet en fait d’avoir notre d’addin lancé au démarrage de Visual Studio pour nos tests ! Mais attention, si un 2ème VS est ouvert, vous risquerez de ne plus pouvoir compiler car il sera impossible de modifier votre assembly .DLL si elle est chargée par une autre instance de VS.

La classe Connect

Notre classe Connect est une implémentation de l’interface IDTExtensibility2 et IDTCommandTarget pour l’ajout d’une commande dans le menu. C’est elle qui est référencée dans notre fichier .AddIn et c’est donc elle qui sera instanciée par Visual Studio pour le chargement de l’ addin.

Comme nous le montre notre Object Browser :

image 

… cette classe implémentera les méthodes suivantes :

  • IDTExtensibility2.OnConnection : appelée au début du chargement de l’ addin par VS.
  • IDTExtensibility2.OnDisconnection : appelée au début du déchargement de l’ addin par VS.
  • IDTExtensibility2.OnAddInsUpdate : appelée quand la liste des addins est modifiée .
  • IDTExtensibility2.OnStartupComplete : appelée en fin de chargement de l’ addin.
  • IDTExtensibility2.OnBeginShutdown : appelée lorsque Visual Studio se ferme.
  • IDTCommandTarget.QueryStatus : appelée pour retourner l’état actuel (activée, désactivée, masquée, etc.) de la commande nommée spécifiée.  
  • IDTCommandTarget.Exec : appelée pour exécuter la commande nommée spécifiée. 

Comme vous le remarquait l’interface IDTExtensibility2 définie les méthodes de chargement/déchargement de notre addin. L’interface IDTCommandTarget  permet quant à elle de créer des commandes nommées qui est ici notre élément dans le menu Tools avec le petit smiley 🙂

Analysons maintenant le code de notre classe Connect générée par Visual Studio ! Vous remarquerez que seules les méthodes OnConnection, QueryStatus et Exec contiennent du code. Libre à vous d’implémenter une logique pour la fermeture de votre add-in si cela est nécessaire.

Lors de l’appel de la méthode OnConnection, l’argument connectMode va permettre de savoir le mode de connexion de l’addin. Dans le code générée par VS, le code de la méthode connexion est executé si le connectMode == ext_cm_UISetup. Comme nous l’indique la MSDN :

La valeur ext_cm_UISetup indique au complément qu’il s’agit de sa première exécution. Dans ce cas, le complément peut ajouter ses commandes personnalisées au menu et à la barre d’outils. Sinon, il peut ignorer cette étape.

Dans d’autre cas, on préféra utiliser les modes AfterStartup ou Startup pour permettre la création de fenêtres au démarrage ou initialisation de la logique de notre application au démarrage de VS.

La suite du code montre un « try..catch » (qu’il conviendrai d’externaliser dans une méthode privée) permettant la récupération du nom du menu « Tools ». En effet comme l’indique le commentaire, ce code permet de rechercher dans le fichier CommandBar.resx quel est le nom du menu Tools en fonction de la culture de VS. En version anglaise (EN), le nom est bien sûr « Tools » mais en version française (FR) cela devient « Outils », et cela change pour les versions JP, ES, IT, RU,  etc….

Une fois le nom récupéré on pourra récupérer la CommandBarPopup par le code :

Et ainsi ajouter notre bouton :

Vous remarquerez dans l’appel de la méthode AddNamedCommand2 les différents paramètres pour notre bouton comme par exemple son nom, son titre et son tooltip. Mais où est donc spécifié notre image (smiley) ? C’est en fait le « 59 » qui détermine l’icône de notre bouton !

Il s’agit en effet du n° de FaceID dont vous retrouverez la liste complète sur la page http://www.kebabshopblues.co.uk/2007/01/04/visual-studio-2005-tools-for-office-commandbarbutton-faceid-property/. On y retrouve notre n° 0059 représentant notre smiley jaune.

Nous verrons dans un autre post comment définir sa propre icône !

Une fois notre addin « connecté » et le bouton ajouté dans le menu Tools, voyons l’implémentation de l’interface IDTCommandTarget et de ses deux méthodes : QueryStatus et Exec.

La méthode QueryStatus permet de définir le status de notre bouton dans le menu. Nous pourrions par exemple implémenter une logique où le bouton serait grisé si l’addin est déjà lancé par exemple.

Dans le code actuel il n’en n’est rien. Le bouton est toujours activé et visible comme l’indique le code :

La méthode Exec quant à elle implémente la logique lors du click du bouton. Il convient d’abord de vérifier quel bouton est cliqué en testant le paramètre commandeName.

Dans le code généré par Visual Studio, aucune action n’est effectuée. Pour notre démo nous allons ajouter la référence vers System.Windows.Forms pour afficher une MessageBox. Voici le code complet de notre méthode Exec :

Relançons maintenant notre projet (F5) et observez le résultat lors du click sur notre bouton :

image

Conclusion

Vous voilà maintenant introduit dans le développement d’add-in pour Visual Studio 2005/2008. Un addin est donc une assembly .NET contenant une classe nommée généralement Connect qui implémente l’interface IDTExtensibility2 et est responsable de la « Connexion » et « déconnexion » de l’addin à Visual Studio. Chaque add-in étant accompagné d’un fichier de description au format XML (.AddIn) placé dans un des répertoires de Visual Studio pour préciser les informations sur l’add-in (nom, fichier de l’assembly, nom de la classe Connect, etc…) et ainsi être chargé au démarrage de l’IDE Visual Studio.

Dans la prochaine partie nous verrons comment créer des fenêtres dans Visual Studio.

.NET,visual studio
Share this Story:
  • facebook
  • twitter
  • gplus

Comments(3)

  1. Trackback: [VS Extensibility] Part 2 : créez vos fenêtres d’outils avec CreateToolWindow2 ! | Sebastien.warin.fr

  2. Trackback: [VS Extensibility] Part 3 : Quelques interactions avec Visual Studio | Sebastien.warin.fr

  3. MEG
    le 9 mai 2009 à 16:37

    c’est super

Leave a comment

Ce site utilise Akismet pour réduire les indésirables. En savoir plus sur comment les données de vos commentaires sont utilisées.

Comment