Bonjour,
Je suis confronté à un problème sur lequel je me casse un peu la tête depuis quelques jours :
J'ai un serveur COM qui se présente sous la forme d'un exécutable. Celui-ci déclare de nombreux "TAutoObject" (que je modifie via la bibliothèque de type). Tous ces objets automation dispose du support des événements, c'est-à-dire qu'ils offrent la possibilité pour le client de recevoir des événements depuis le serveur COM.
Les applications clientes accèdent aux différents objets automation grâce à la bibliothèque de type importée dans Delphi depuis l'exécutable du serveur COM, chaque objets se présentent alors simplement sous la forme d'un composant à poser sur les fiches de l'application cliente. Ces composants contiennent les méthodes et événements de l'objet Automation et permettent également de préciser de quelle manière on se connecte/on instancie l'objet automation.
Voilà mon problème : lorsqu'une application plante, ou que son processus est tué brutalement alors la génération d'un événement depuis le serveur sur une des instances d'objet automation créées par ce processus va entrainer une exception ("serveur RPC indisponible", bien qu'en l'occurrence ici c'est l'application cliente qui n'est plus disponible), du coup le serveur COM devient inutilisable puisque de nombreuses méthodes des objets automation génèrent des événements en retour... C'est pourquoi j'ai trouvé un moyen de rattraper ces exceptions ("serveur RPC indisponible"), pour détecter un objet automation "orphelin", ou plus précisément un "EventSink" orphelin (un EventSink correpond grosso modo à un "répartiteur d'événements" sur une application cliente utilisant l'instance de l'objet automation qui génère ces événements). Je supprime alors ces "EventSink" qui ne pourront de toutes façons plus répondre (à mon sens, mais le message d'erreur n'est pas suffisament explicite pour en être sûr, mais j'ai considéré que c'était le cas). Je considère alors l'objet automation réellement orphelin lorsque son "SinkList" ne contient plus de "EventSink" (car une instance d'un objet automation peut avoir plusieurs "EventSink", puisque mes applications clientes utilisent le mode de connexion "ckRunningOrNew", c'est-à-dire qu'elles n'instancient pas systématiquement un nouvel objet automation mais utilisent ceux déjà existant).
Tout cela fonctionne "très bien" si ce n'est que c'est un peu compliqué à mettre en oeuvre... à l'exception d'un problème :
Certaines applications ne passe pas par les composants de la bibliothèque de type mais directement par des interfaces, qui sont créés en appelant la méthode "CoXXX.Create". Le problème de ces interfaces, c'est qu'elles n'instancient pas d'"EventSink" (en effet elle utilise uniquement l'interface de base, elle ne peuvent recevoir d'événements de la part du serveur), et du coup je suis susceptible de supprimer des objets automation qui en réalité sont encore utilisé uniquement de cette façon, provoquant par là une erreur sur l'application cliente au prochain appel de méthode de l'objet automation via l'interface.
Hors je veux vraiment pouvoir nettoyer les "instances orphelines" de mes objets automations, c'est-à-dire celles qui ne sont plus utilisées car le processus qui les a créé a été détruit brutalement. Et permettre ainsi à mon serveur automation de s'arrêter tout seul dès lors qu'il n'est réellement plus utilisés.
Précision pas forcément utile : le serveur COM et les applications clientes fonctionnent sur la même machine.
Ma question :
Existe-t-il un moyen fiable et relativement simple de détecter ces "instances orphelines" ?
Je sais que je vous ai noyé de détails assez durs à comprendre sans mettre une ligne de code mais je n'ai pas le code sous la main au moment ou je poste, et je ne sais pas s'il sera d'une grande aide car je ne pourrais qu'en mettre de toutes petites parties vu la taille du projet. Je le ferai demain tout de même.
Merci à ceux qui auront eu le courage de me lire, et encore plus à ceux qui oseront répondre !
Partager