I. La création du composant COM en .Net (C#)▲
Création du projet à partir de Visual Studio 2010, nous sélectionnons le menu Fichier>Nouveau>Projet>Bibliothèque de classes. Nous nommons ce nouveau projet ComTutoriel. Ce nouveau projet contient donc :
- le fichier AssemblyInfo.cs : contenant les informations de notre assembly. Celui-ci devra être modifié plus tard pour permettre son utilisation en tant qu'objet COM ;
- les références de base ;
- un fichier Class1.cs qui est la première classe de notre projet. Celui-ci va être renommé en COMInterface pour obtenir ceci :
I-A. Ajout d'un formulaire▲
Pour les besoins des tests, nous allons créer un nouveau formulaire Windows. Pour ce faire, sélectionnez le projet et cliquons sur le bouton droit de la souris. Dans le menu contextuel, sélectionnons Ajouter>Formulaire Windows. Nous nommerons celui-ci FrmTest. Nous avons donc pour le moment un formulaire ressemblant à ceci :
I-B. Ajout de boutons dans le formulaire▲
Nous avons simplement ajouté 2 boutons à ce nouveau formulaire : BtnOk et BtnAnnuler. Le code pour chaque bouton est le suivant :
private
void
btnOk_Click
(
object
sender,
EventArgs e)
{
DialogResult =
DialogResult.
OK;
Close
(
);
}
private
void
btnAnnuler_Click
(
object
sender,
EventArgs e)
{
DialogResult =
DialogResult.
Cancel;
Close
(
);
}
Ce code permettra donc à la fonction appelante de notre formulaire, de savoir à la fermeture de celui-ci sur quel bouton l'utilisateur aura appuyé. La propriété DialogResult ayant été initialisée à la valeur Cancel dans le constructeur, dans le cas où l'utilisateur cliquerait sur la croix du formulaire :
public
FrmTest
(
)
{
InitializeComponent
(
);
DialogResult =
DialogResult.
Cancel;
}
I-C. Création des propriétés des méthodes▲
Revenons à notre classe COMInterface. Nous y créons une propriété Caption qui sera attribuée comme titre au formulaire que nous venons de faire, ainsi qu'une méthode ShowForm pour afficher notre formulaire. Nous obtenons donc ceci :
namespace
ComTutoriel
{
public
class
COMInterface
{
public
string
Caption {
get
;
set
;
}
public
void
Persist
(
string
FilePath)
{
FrmTest dial =
new
FrmTest
(
);
dial.
Text =
Caption;
}
}
}
I-D. Ajout de la références au composants System.EnterpriseServices▲
Pour pouvoir utiliser notre librairie comme une librairie COM, nous devons lui ajouter une référence vers le composant System.EnterpriseServices. Pour cela, sélectionnons dans l'explorateur de solution, bouton droit de la souris pour avoir le menu contextuel et ensuite Ajouter une référence. Rechercher alors System.EnterpriseServices dans la liste de l'onglet .NET
I-E. Signature du composant ▲
Pour pouvoir éventuellement enregistrer notre composant comme un objet COM dans le Global Assembly Cache, il nécessite une signature de son éditeur. Les assemblys sans nom fort doivent être installés dans le répertoire de l'application cliente. Pour signer notre assembly. Il faut donc ouvrir la fenêtre des propriétés de notre projet via par exemple le menu Projet > Propriétés de <Nom du projet> :
Nous donnons un nom pour le fichier de clé, et nous y appliquons un mot de passe. Après cette action vous verrez apparaître dans l'explorateur de solution un nouveau fichier KeyComTutoriel.pfx. Ceci indique que votre assembly est maintenant signé.
I-F. Modification des propriétés du fichier AssemblyInfo.cs▲
Dans l'explorateur de solution, nous ouvrons le fichier AssemblyInfo.cs situé dans le dossier Propriétés. Dans celui-ci rajouter les lignes suivantes :
using
System.
EnterpriseServices
// Le nom du composant COM que nous créons
[assembly: ApplicationName(
"COMTutoriel"
)]
// Indique que le composant s'exécutera dans le processus du client et non pas
// par le processus le système (ActivationOption.Server)
[assembly: ApplicationActivation(ActivationOption.Library)]
Dans le fichier AssemblyInfo.cs, nous modifions également la ligne suivante comme indiquée :
// Permet de rentre les types définis dans l'assembly
// visibles pour les composants COM.
[assembly: ComVisible(true)]
I-G. Extraction de l'interface du composant▲
Maintenant retournons dans le fichier COMInterface.cs. Pour pouvoir exposer notre assembly comme composant COM, l'application cliente récupère les types, propriétés, méthodes… définis via une interface. Nous allons donc maintenant extraire l'interface de notre classe COMInterface. Pour ce faire dans le menu Refactoriser, nous sélectionnons le sous-menu Extraire l'interface. La fenêtre suivante nous permet de sélectionner les membres de la classe que nous désirons exposer :
Dans le cas de l'exemple, nous laissons tout sélectionné.
I-H. Paramétrisation de l'interface et du composant ▲
Dans la classe COMInterface, nous rajoutons une directive Using pour System.Runtime.InteropServices, ainsi que la ligne [ClassInterface(ClassInterfaceType.None)]. Celle-ci permet de spécifier le type d'interface de classe à générer pour une classe exposée à COM. Dans notre cas, nous choisissons ClassInterfaceType.None, car il indique qu'aucune interface n'est générée automatiquement pour la classe vue que nous en avons explicitement implémentée une.
Notre classe COMInterface doit maintenant ressembler à ceci :
[ClassInterface(ClassInterfaceType.None)]
public
class
COMInterface :
System.
EnterpriseServices.
ServicedComponent,
ComTutoriel.
ICOMInterface
{
public
string
Caption {
get
;
set
;
}
public
void
FormShow
(
)
{
FrmTest dial =
new
FrmTest
(
);
dial.
Text =
Caption;
dial.
ShowDialog
(
);
}
}
Ne pas oublier de marquer notre interface également comme publique :
using
System;
namespace
ComTutoriel
{
public
interface
ICOMInterface
{
string
Caption {
get
;
set
;
}
void
FormShow
(
);
}
}
I-I. Implémentation des événements▲
Ajout d'événements dans notre assembly pouvant être interceptés par notre application VB6.
Il est possible d'ajouter des événements à notre assembly qui pourront être interceptés par notre application cliente VB6. La procédure est la suivante :
- nous devons définir une interface d'événement dans le code managé. Les noms des différentes méthodes de l'interface devant être identiques au nom des événements. Dans notre cas, nous allons définir deux événements, un déclenché lors de la sélection du bouton OK de notre petite fenêtre, le deuxième déclenché par le bouton Annuler ;
// Déclaration des délégés des événements
public
delegate
void
ClickOkDelegate
(
);
public
delegate
void
ClickCancelDelegate
(
);
// Attribut pour connecter l'interface du récepteur d'événement à la classe managée
[InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIDispatch)]
public
interface
ComInterfaceEvents
{
void
ClickOk
(
);
void
ClickCancel
(
);
}
- déclarer les deux événements dans l'interface générée tout à l'heure ou régénérer celle-ci. Notre interface finale devrait donc ressembler à ceci :
using
System;
namespace
ComTutoriel
{
interface
ICOMInterface
{
// Déclaration des événements
event
ClickCancelDelegate ClickCancel;
event
ClickOkDelegate ClickOk;
// Déclaration des propriétés
string
Caption {
get
;
set
;
}
// Déclaration des méthodes
void
FormShow
(
);
}
}
- connecter notre d'interface d'événement à notre classe managé et déclarer nos événements. La connexion de l'interface d'événement ce fait par l'ajout de l'attribut suivant :
[ClassInterface(ClassInterfaceType.None)]
[ComSourceInterfaces(
typeof
(ComInterfaceEvents))]
public
class
COMInterface :
System.
EnterpriseServices.
ServicedComponent,
ComTutoriel.
ICOMInterface
{
...
Et voici l'implémentation de nos méthodes correspondant à nos événements :
// Déclaration des événement
public
event
ClickOkDelegate ClickOk;
public
event
ClickCancelDelegate ClickCancel;
- pour terminer nous modifions un peu notre méthode pour rajouter la gestion du retour de notre fenêtre :
// Implémentation des méthodes
public
void
FormShow
(
)
{
FrmTest dial =
new
FrmTest
(
);
dial.
Text =
Caption;
if
(
dial.
ShowDialog
(
) ==
System.
Windows.
Forms.
DialogResult.
OK)
{
ClickOk
(
);
}
Else
{
ClickCancel
(
);
}
}
I-J. Compilation du projet▲
Nous pouvons maintenant compiler le projet et vérifier l'absence d'erreur.
I-K. Enregistrement du composant ▲
Maintenant si nous désirons utiliser notre nouveau composant dans un projet VB6, nous devons l'enregistrer. Pour ce faire nous devons utiliser la commande suivante dans la console de Windows :
regsvcs /appname:ComTutoriel D: \ComTutoriel\ComTutoriel\bin\Debug
\ComTutoriel.dll
ou
/appname : spécifie le nom de l'application COM+ à rechercher ou à créer.
D: \ComTutoriel\ComTutoriel\bin\Debug\ComTutoriel.dll : représente le chemin complet vers la dll résultante de la compilation de notre projet.
Attention : pour exécuter cette commande, vous devez ouvrir la console en mode administrateur.
Remarque : dans ce cas, si vous voulez désinstaller le composant, vous pouvez utiliser la commande :
regsvcs /u D:\ComTutoriel\ComTutoriel\bin\Debug
\ComTutoriel.dll
Si nous regardons dans la fenêtre Services de composants (Panneau de configuration > Outils d'administration > Services de composants), on trouvera notre nouveau composant dans la liste des applications COM+.
Remarque générale concernant regsvcs :
Le dossier contenant cet utilitaire ne se trouve pas dans la variable d'environnement PATH, il faut connaître l'emplacement de cet exécutable. De plus celui-ci peut être présent en plusieurs versions sur un poste où sont installées plusieurs versions du FrameWork (ce qui est assez courant).
Si vous essayez d'enregistrer votre composant avec une version de regsvcs qui ne correspond pas à la version du FrameWork avec laquelle a été compilé le composant, vous obtiendrez un message d'erreur.
Pour connaître l'emplacement de l'exécutable correspondant au dernier FrameWork installé et donc utilisé sur le pc, il faut aller voir dans la base de registre :
- dans le cas par exemple du FrameWork 4 :
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\NET Framework Setup\NDP\v4\Full\InstallPath - dans le cas ou seulement le client profile est installé :
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\NET Framework Setup\NDP\v4\Client\InstallPath
Lorsqu'on est en phase de développement, il est indispensable de passer par l'outil regsvcspour que le composant soit inscrit comme objet COM et donc référençable par les clients écrits en VB6 lors de leurs phases de développement.