Par Eric Vernié, Responsable relation technique développeurs - Microsoft France
Document de référence
Révision 1.0
Technologies abordées
Visual Basic 6.0
Visual Basic 2005
Framework .Net 2.0
Téléchargez l'application d'Eric
Sur cette page
Résumé
Introduction
Création automatique d’un proxy .NET pour COM
Conclusion
Résumé
Dans cet article, vous découvrirez comment créer un objet .NET avec Visual Basic 2005, et le consommer avec Visual Basic 6.0.
Introduction
Il est clair que lorsque nous avons investis du temps et de l’argent dans le développement d’application, nous ne pouvons pas toujours nous permettre de tout changer ou de tout reconstruire à chaque fois qu’une nouvelle version d’un produit, ou d’un outil apparaît sur le marché.
C’est d’autant plus vrai, qu’entre Visual Basic 6.0 et Visual Basic pour la plate-forme .NET il y a eu beaucoup de changements et que la migration automatique d’un projet, ne va pas sans quelques inconvénients.
Mais il est toujours sain de se poser des questions concernant l’évolution de notre application Visual Basic 6.0.
Faut-il tout reprendre de zéro ?
Dois-je réécrire mon application entièrement ?
Dois-je migrer le code ?
Dois-je réutiliser des parties existantes, Dois-je faire du code Mixte ?
Autant de questions importantes que vous devez vous poser et que auxquels je ne peux répondre ici, car cela dépend essentiellement de votre application. Mais je vous recommande la lecture de l’article Mise en œuvre d’une stratégie de migration de Visual Basic 6.0 vers Visual Basic .NET qui pourra vous aider dans votre démarche.
Dans cet article, ce que je vous propose c’est de créer du code Mixte. C'est-à-dire, de pouvoir ajouter des fonctionnalités à votre application Visual Basic 6.0, tout en tirant profit de la plate-forme .Net 2.0.
Rendre un composant .NET visible pour COM.
Comme je le sous entendais en introduction, il existe désormais deux mondes pour les développeurs Visual Basic. Deux mondes qui doivent cohabiter sans doute pour quelques temps encore.
Il existe déjà depuis quelques années le monde COM sur lequel s’appui Visual Basic 6.0, puis très récemment le monde .NET sur lequel ont été construites les nouvelles moutures de Visual Basic. (2002/2003 et 2005)
Ces deux mondes sont totalement différent, mais quoi que vous entendiez de ci de la, la plate-forme .NET est un indéniable atout pour les développeurs Visual Basic.
Pour que ces deux mondes puissent vivre en harmonie, et que tout l’investissement fait sur COM ne soit pas remisé au placard, Microsoft a incorporé dans la plate-forme .NET, une technologie nommée « ComInterop », qui permet d’utiliser :
Pour notre part, nous allons nous focaliser sur la manière de construire un Composant .NET visible pour COM.
Avant d’aller plus loin je souhaiterai faire un rapide rappel sur COM (Common Object Model).et Visual Basic 6.0
Le modèle COM Visual Basic 6.0
Lorsqu’avec Visual Basic 6.0, vous créez un projet de type « DLL ActiveX », est crée une classe nommée par défaut Class1, dans laquelle vous pouvez ajouter des méthodes, des propriétés, etc…
Lors de la compilation, en définitif, est construit pour vous toute l’infrastructure COM.Par exemple, supposons que vous ayez une classe nommée AccesDonnees possédant une méthode unique TrouverClient(IDClient as integer), le compilateur de VB6, incorpore pour vous par défaut, les informations de type dans la DLL. Dans le monde COM ces informations de type sont en générale décrites dans un fichier avec extension TLB (Type Library), que vous pouvez créer en cochant la case appropriée dans l’interface de VB6 (cf. Figure 1)
Figure1
Est donc généré par le compilateur des informations que vous retrouvées dans la Figure 2
[
uuid(8176057F-DE8A-4013-9837-0857FFC05E7F),
version(1.0),
custom(50867B00-BB69-11D0-A8FF-00A0C9110059, 9782)
]
library MaDLLActiveX
{
// TLib : // TLib : OLE Automation : {00020430-0000-0000-C000-000000000046}
importlib("stdole2.tlb");
// Forward declare all types defined in this typelib
interface _AccesDonnees;
[
odl,
uuid(6ECAB544-0A59-4962-8743-B88A1719253C),
version(1.0),
hidden,
dual,
nonextensible,
oleautomation
]
interface _AccesDonnees : IDispatch {
[id(0x60030000)]
HRESULT TrouverClient(
[in, out] short* IDClient,
[out, retval] BSTR* );
};
[
uuid(7F55DE1D-A5B7-466C-B678-DDF1FCFBC907),
version(1.0)
]
coclass AccesDonnees {
[default] interface _AccesDonnees;
};
};
Figure 2 : Informations contenues dans la TLB
En tant que développeurs Visual Basic 6.0, vous n’avez pas besoin de connaître ses informations, par contre il est intéressant de les appréhender pour bien comprendre la suite de l’article.
La librairie ce nomme MaDLLActiveX et aura comme numéro d’identification (GUID) 8176057F-DE8A-4013-9837-0857FFC05E7F
Elle est constituée d’une interface _AccesDonnees avec comme numéro 6ECAB544-0A59-4962-8743-B88A1719253C. Cette interface possède une méthode TrouverClient et dérive de l’interface IDispatch.
A noter que c’est bien le compilateur VB6 qui a crée pour nous cette interface en préfixant le nom de notre classe AccesDonnees par le caractère de soulignement « _ ».
L’interface IDispatch permet de rendre notre composant, compatible avec des langages de scripting tel que VBScript en permettant les liaisons tardives. (Vous savez l’instruction CreateObject() !!!)
Enfin nous retrouvons notre Class AccesDonnees, sous forme de CoClass avec un numéro d’identification 7F55DE1D-A5B7-466C-B678-DDF1FCFBC907 et qui dérive de l’interface _AccesDonnees.
Toute ActiveX DLL crée en Visual basic 6.0 aura cette forme.
Une remarque que je souhaiterai ajouter ici. A chaque compilation les numéros d’identifications peuvent changer si vous n’y faite pas attention, rendant ainsi votre objet incompatible avec des clients qui auraient déjà été liés à votre ActiveX et qui n’auraient pas été recompilés en même temps. Vous savez le message « Erreur 429 ne peut créer l’objet !!!!»…..
Comme il n’est pas possible de maitriser ces numéros d’identifications et donc de réutiliser les mêmes à chaque fois, il est impératif d’avoir une bonne maitrise du versionning de vos composants COM.
Résumons ce que nous venons de voir.
Notre ActiveX DLL est donc constituée :
-
D’un numéro d’identification qui l’identifie de manière unique
-
Une interface avec son numéro qui l’identifie de manière unique
-
Une CoClass avec son numéro d’identification
Chaque numéro d’indentification est construit sous la forme de Global Unique Indentifier (GUID) codé sur 128 bits qui permet justement de construire des numéros uniques.
Une fois que vous avez ces notions en tête, passons à la création de notre proxy .NET pour COM.
Construire le proxy .NET pour COM
Dans Visual Basic 2005 (Express ou toute autre version)
-
Créez un nouveau projet de type « Bibliothèque de classes ». (Laissez le nom par défaut)
Vous retrouverez dans le fichier Class1.vb le code suivant :
Public Class Class1
End Class
-
Pour rendre Class1, visible par COM, nous allons utiliser l’attribut du Framework .NET ComClassAttribut. Comme ceci :
<ComClass(InterfaceShadows :="False")>
_
Public Class Class1
Sub MaMethodeNET()
MsgBox(“Bonjour en VB 2005”)
End Sub
End Class
Pour l’instant avec cet attribut, j’informe qu’il faudra créer dans la librairie de Type (TLB) l’interface et d’utiliser pour la coClass et l’interface des numéros d’identifications aléatoires.
-
Pour ajouter un numéro d’identification à la librairie elle-même, il faudra cocher la case « Rendre l’assembly visible par COM » que vous trouverez en activant les propriétés de la classe, puis l’onglet Application, puis le bouton « Informations de l’assembly »
-
Compilez le projet, la DLL ClassLibrary1.dll est ainsi construite.
Enregistrement de votre proxy et création de la librairie de Type.
-
Si vous possédez une version autre que Visual Basic Express, vous pouvez enregistrer directement la DLL en cochant la case : « Enregistrer pour COM Interop », dans l’onglet « compilation », des propriétés du projet, ou vous pouvez utiliser l’outil regasm.exe :
Regasm ClassLibrary1.DLL /tlb
L’instruction /tlb créée la librairie de type ClassLibrary1.tlb
-
Si vous n’avez que Visual basic Express, vous pouvez également utiliser l’outil Regasm que vous trouverez en téléchargeant le SDK du FrameWork.NET 2.0.
-
Si vous ne souhaitez pas télécharger le SDK, vous pouvez utiliser l’outil que j’ai développé à cet égard.
Pour l’utiliser, installez-le (binaire fourni en téléchargement avec cet article), allez directement à l’onglet « Enregistrement »
Activez le menu Assembly, et chargez l’assembly ClassLibrary1.dll que vous venez de créer. Cela à pour effet d’activer le bouton « Enregistrement »
Appuyez sur le bouton « Enregistrement »
Si tout se passe correctement vous devez recevoir le message
Non seulement l’outil enregistre le composant, mais crée également une TypeLibrary nommée ClassLibrary1.tlb que nous allons utiliser par la suite dans Visual Basic 6.0
Consommation du Proxy .NET dans Visual Basic 6.0
-
Allez dans Visual basic 6.0
-
Ajoutez une référence au proxy en prenant comme référence ClassLibrary1.tlb
-
Puis ajoutez le code de consommation sous l’évènement click d’un Bouton
Private Sub Command1_Click()
Dim wrapper As ClassLibrary1.Class1
Set wrapper = New ClassLibrary1.Class1
wrapper.MaMethodeNET
End Sub
Exécutez le programme, vous devez obtenir le message
J’aimerai attirer votre attention sur le fait suivant :
En utilisant l’attribut ComClass, avec comme unique paramètre InterfaceShadows=true, nous restons dans une construction sensiblement identique à Visual Basic 6.0. C'est-à-dire, que nous ne maitrisons pas la création des numéros d’identification pour notre CoClass, Interface voir nos évènements ou tous autres types. Il est donc de bon ton d’aller un peu plus loin, et de forcer l’utilisation de nos propres GUID évitant de polluer notre registre avec d’anciennes versions qui auraient été générées automatiquement. Pour ce faire notre code doit être modifié comme ceci :
<ComClass(Class1.ClassID, _="
Class1.InterfaceID=", _="
Class1.EventID=")>
_
Public Class Class1
Public Const ClassID As String = "03c3452d-6b57-4c54-8fed-46abdda0ece9"
Public Const InterfaceID As String = "62fba3d5-a0d0-42d2-adb1-2d7a4d9aeded"
Public Const EventID As String = "a78a4d65-3462-496e-be86-f9be77022eff"
Sub New()
MyBase.New()
End Sub
Sub MaMethodeNET()
MsgBox("Bonjour en VB 2005")
End Sub
End Class
On force l’utilisation d’un Global Unique Identifier, pour la coClass, l’interface et les évènements. Pour obtenir les GUID, vous avez plusieurs solutions.
-
Si vous utilisez une version autre que la version Visual basic Express, un outil est intégré nommé « Create GUID » que vous pouvez activer par le biais du menu Outils\Create Guid.
Attention de bien sélectionner le format N°4
-
Si par contre vous utilisez Visual basic Express, vous pouvez utiliser un second outil que j’ai développé et qui est disponible en téléchargement avec cet article, et qui fait la même chose.
Une fois le Guid crée, copiez le dans le presse papier avec le bouton approprié, puis allez dans votre code et collez-le.
Création automatique d’un proxy .NET pour COM
Si comme moi, vous voulez automatiser la création d’un proxy, vous pouvez :
-
Soit créer un extrait de code avec Visual basic 2005 et le réutiliser.
Je ne vais pas rentrer ici dans les détails, mais sachez qu’il existe un outil SnippetEditor, qui mâche le boulot pour vous
-
Soit utiliser mon outil qui est en téléchargement avec cet article, dont voici quelques explications.
En un mot, l’outil « Créer proxy COM » permet de générer tout le code Visual Basic 2005 en un seul click.
Comment ça marche ?
Au lancement de l’application, vous tombez sur le 1er Ecran. L’écran Informations, vous permet d’ajoutez un entête sous forme de commentaire dans le code du proxy :
Ecran informations
L’écran Type du Proxy, vous permet de définir le minimum requis pour créer votre Proxy. Un espace de nom, un nom de classe, une méthode de type Sub sans paramètre, ainsi qu’un événement .NET disponible pour COM.
Vous pouvez dés à présent allez directement à l’écran générer en sélectionnant l’onglet Générer.
Cochez la case Sauvegarder le proxy dans un fichier pour créer un fichier avec extension *.vb que vous pourrez réutiliser dans une solution
Ensuite, activez le bouton
pour générer le proxy qui s’affiche dans la fenêtre
Dans mon exemple, le proxy a été crée dans un fichier nommée Class1.vb (dans le répertoire de l’application) dont voici le détail.
Imports System
Imports System.Runtime.InteropServices
Imports Microsoft.VisualBasic
'Titre : Création d'un composant .NET/COM pour Visual Basic 6.0
'Auteur : Eric Vernié
'Date : 13/06/2006
'Mise à jour :
'Description : Exemple de Wrapper COM pour Visual Basic 6.0
'Pour rendre visible l'assembly pour COM, décommenter les lignes suivantes <Assembly...>
'Ou n'oubliez pas de cocher la case Rendre Visible pour COM
'<Assembly: ComVisibleAttribute(True=")>
'<Assembly: Guid="("8ddbae82-ee79-4401-954b-2bc490838c2e")>
'Pour Enregistrer l'assembly, utiliser l'outil regasm
Namespace Microsoft.DPE
<Microsoft.VisualBasic.ComClass("0ca724be-3ae8-4462-913c-47c0ff7e8f00",
"868e0078-eff7-43c3-83c6-0d6a7211158b", "281261cd-b6f2-4254-ace1-8da4c8436eb4")>
_
Public Class WrapperCOM
Public Event MonEvent As MonHandler
<ComVisible(true)>
_
Sub Initialiser()
'TODO : Ajoutez votre code d'initialisation
End Sub
'Méthode à tester Via VB6
<ComVisible(true)>
_
Sub MethodeTest()
Msgbox("Hello le monde !!!")
End Sub
'Cette méthode n'est pas visible pour COM
<ComVisible(false)>
_
Sub AutreMethode()
End Sub
<ComVisible(true)>
_
Sub SurEvenement(ByVal timeout As Integer)
System.Threading.Thread.Sleep(timeout)
RaiseEvent MonEvent(me,new EventArgs())
End Sub
Public Delegate Sub MonHandler(ByVal Sender As Object, ByVal e As System.EventArgs)
End Class
End Namespace
On y retrouve l’entête sous forme de commentaires, l’espace de nom Microsoft.DPE, une classe accrochée à un attribut ComClass, dont les GUIDS ont été crée automatiquement, la méthode Initialiser(), ainsi que l’évènement MonEvent de type MonHandler.
Vous pourrez remarquer que j’y ai ajouté aussi plusieurs méthodes de test comme la Sub, MethodeTest() qui affiche un message, ainsi que la méthode SurEvenement qui lève notre évènement au bout d’un certain temps. Ce code est prêt à l’emploi et vous pouvez déjà le tester dans Visual Basic 6.0. Point que nous aborderons un peu plus loin.
Le bouton
permet de valider les éventuels changements que vous auriez faits directement dans la fenêtre. En effet, rien ne vous empêche à ce niveau de rajouter manuellement du code vb. Par exemple, vous pouvez ajouter manuellement des méthodes, des propriétés, des événements, tout le code VB 2005 qui vous passe par la tête.
Avant de tester ce proxy dans Visual Basic 6.0, vous devez compiler le proxy et l’enregistrer. Deux méthodes s’offrent à vous.
-
Si vous avez sauvegardé le proxy dans un fichier *.vb, avec Visual Basic 2005, vous pouvez le réutiliser et le compiler. Pour l’enregistrement refaite les étapes vues à la section « Enregistrement de votre proxy et création de la librairie de Type »
-
Ou alors sans sortir de l’outil, activez l’onglet « Compiler » vous devez tomber sur l’écran suivant
Cet écran, comme son nom l’indique vous permettra de compiler et d’enregistrer automatiquement l’assembly en activant le bouton
et en cochant la case Enregistrer pour COM. Voici ce que vous devez obtenir
Le faite de cocher la case enregistrer pour COM, crée également une librairie de type nommée Microsoft.DPE.WrapperCOM.tlb que nous allons réutiliser dans Visual Basic 6.0
Pour consommer et tester notre Proxy
-
Allez dans Visual basic 6.0
-
Créez un projet de type EXE
-
Ajoutez une référence à la librairie Microsoft.DPE.WrapperCOM.tlb
-
Puis ajoutez le code suivant
Public WithEvents objNet As Microsoft_DPE_WrapperCOM.WrapperCOM
Private Sub Command1_Click()
Set objNet = New Microsoft_DPE_WrapperCOM.WrapperCOM
objNet.SurEvenement (1000)
objNet.MethodeTest
End Sub
Private Sub objNet_MonEvent(ByVal Sender As Variant, ByVal e As mscorlib.EventArgs)
MsgBox ("J'ai fini mon travail")
End Sub
Et voila c’est fait, vous avez crée votre premier proxy COM prêt à l’emploi. A vous de jouer maintenant. Très prochainement, vous pourrez retrouver sur le site VBasic de MSDN France sous formes de Vidéos des exemples d’utilisation des librairies du FrameWork .NET 2.0.
En attendant vous pouvez aller voir l’article que j’ai écrit sur le multi-threading et Visual Basic 6.0 qui s’inspire de cette technique de COMInterop.
J’aimerai terminer rapidement par les écrans, « Méthodes », « Propriétés », « Evènements » qui vous permettent d’ajouter à votre proxy les éléments qu’ils décrivent. Prenons par exemple l’écran Méthodes (Je vous laisse découvrir les autres par vous-même)
Cet écran vous permet d’ajouter des Méthodes de type Sub (sans type de retour) ou des Méthodes de type Function, les deux avec ou sans paramètre.
Par exemple, pour ajouter une méthode nommée ClientExiste, qui prend en paramètre un long, et un tableau de String et qui retourne un Boolean, suivez les étapes suivantes :
-
Entrez le nom de la méthode : ClientExiste
-
Cochez la case : Function
-
Sélectionnez le type de retour : System.Boolean
-
Entrez un nom de paramètre : IDClient
-
Cochez ByVal ou ByRef
-
Sélectionnez le type : System.Int32
-
Ajoutez le paramètre en activant le bouton
-
Entrez un second nom de paramètre avec des parenthèses: MonTableau()
-
Sélectionnez Byref
-
Sélectionnez le type : System.String
-
Ajoutez le paramètre en activant le bouton
-
Ajoutez la méthode en activant le bouton
Il est important d’ajouter d’abord les paramètres, avant d’ajouter la méthode. Répétez l’opération autant de fois que vous avez de méthodes
Pour générer le proxy avec les nouvelles informations, activez directement le bouton générer ou click sur bouton droit de la souris, menu générer. Contre toute attente, le code suivant dans notre cas doit être ajouté au proxy.
<ComVisible(true)>
_
Function ClientExiste(ByVal IDClient As Integer, ByVal MonTableau() As String) As Boolean
End Function
Compilez le code avec l’outil pour valider qu’il n’y a pas d’erreur. A noter que vous pouvez supprimer paramètre par paramètre ou tous les paramètres d’un coup idem pour les méthodes.
Si vous souhaitez ajouter des propriétés et des méthodes, le même principe est applicable, si ce n’est que pour les propriétés, l’outil génère à la fois la méthode Get et Set selon les cas, mais aussi les données membres privées et leur consommation. Comme ceci :
Private _fichierexiste As Boolean
Public Property FichierExiste() As Boolean
Get
Return _fichierexiste
End Get
Set
Me._fichierexiste = value
End Set
End Property
Ca fait gagner du temps ;-)
Conclusion
Nous venons de voir dans cet article, comment il était simple de créer avec Visual Basic 2005 des composants qui soient exploitables dans vos applications Visual basic 6.0.
Avec cette technique il est possible de faire évoluer son application Visual Basic 6.0 préférée tout en profitant des nouveautés du Framework .NET 2.0 et de sa simplicité d’utilisation. L’application évolue en douceur, et vous évoluez en douceur aussi, en appréhendant le Framework 2.0 et Visual basic 2005 à votre rythme.