IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

API, COM et SDKs Delphi Discussion :

Serveur COM : comment détecter une instance d'objet automation "Orphelin" ?


Sujet :

API, COM et SDKs Delphi

  1. #1
    Membre du Club
    Profil pro
    Inscrit en
    Mars 2005
    Messages
    149
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2005
    Messages : 149
    Points : 61
    Points
    61
    Par défaut Serveur COM : comment détecter une instance d'objet automation "Orphelin" ?
    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 !

  2. #2
    Expert éminent sénior
    Avatar de Paul TOTH
    Homme Profil pro
    Freelance
    Inscrit en
    Novembre 2002
    Messages
    8 964
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 55
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Freelance
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Novembre 2002
    Messages : 8 964
    Points : 28 457
    Points
    28 457
    Par défaut
    je n'ai pas la réponse à ta question, mais pour ce genre de problèmes je te recommande de créer un mini projet avec un serveur COM, un client automation et un client interface et de regarder comment tout cela s'articule. COM est assez tordu pour ne pas ajouter à ton problème tout l'aspect métier de ton code

  3. #3
    Membre du Club
    Profil pro
    Inscrit en
    Mars 2005
    Messages
    149
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2005
    Messages : 149
    Points : 61
    Points
    61
    Par défaut
    Citation Envoyé par Paul TOTH Voir le message
    je n'ai pas la réponse à ta question, mais pour ce genre de problèmes je te recommande de créer un mini projet avec un serveur COM, un client automation et un client interface et de regarder comment tout cela s'articule. COM est assez tordu pour ne pas ajouter à ton problème tout l'aspect métier de ton code
    Merci pour ta réponse,

    à vrai dire c'est déjà ce que j'ai fait.

    En fait mon problème est que certaines applis utilise les objets automation
    avec ce type d'instanciation :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    var
       MyAutoObject: IMyAutoObject;
    begin
       MyAutoObject:= CoMyAutoObject.Create;
       MyAutoObject.DoSomething;
       ...
       MyAutoObject:= nil;
    end;
    Hors si l'appli plante, l'instance de l'objet automation n'est pas libérée au niveau du serveur COM et je ne vois pas comment il peut savoir qu'en réalité cette instance n'est plus utilisée par personne. Je sais que ce type d'instanciation va systématiquement créé une instance de l'objet automation car 'CoXXX.Create' appel en interne 'CoCreateInstance'.

    J'ai trouvé une solution pour le cas d'instanciation suivant :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    var
       MyAutoObject: TMyAutoObject;
    begin
       MyAutoObject:= TMyAutoObject.Create( nil )
       try
          MyAutoObject.DoSomething;
             ...
       finally
          MyAutoObject.Free;
       end;
    end;
    ou encore lorsqu'on pose le 'TMyAutoObject' sur une fiche tout simplement.
    En effet le 'TMyAutoObject' va instancier en même temps une interface de type 'TMyAutoObjectEvents' qui va permettre au serveur COM de détecter si l'un d'eux ne répond plus (en rattrapant l'erreur "Serveur RPC indisponible" lorsqu'on effectue un appel sur l'interface 'TMyAutoObjectEvents' depuis le serveur COM)...
    Alors je pourrais tout passer en mode d'instanciation de type "TMyAutoObject" et non "IMyAutoObject" mais j'avais fait cela à l'époque car justement le retour d'événement depuis le serveur COM provoquait des erreurs par moment, du type "un appel sortant a eu lieu durant un asynchrone" ou ce genre de chose... à l'époque j'étais plutôt novice et j'avais pas trop cherché à comprendre si mon code était un peu scabreux, j'ai simplement viré les événements en passant par des interfaces. Mais c'est pourquoi je peux pas choisir cette solution...

    Quelqu'un connait-il une autre solution "magique" pour détecter qu'une interface n'est plus utilisée même si son compteur de référence n'est pas = 0, en gros il faudrait pouvoir retrouver la source de chaque incrément du compteur de référence...

Discussions similaires

  1. Cast à partir d'une instance d'objet ? Comment faire ?
    Par t00f- dans le forum Windows Mobile
    Réponses: 1
    Dernier message: 23/05/2008, 11h05
  2. Réponses: 4
    Dernier message: 23/04/2008, 15h29
  3. [VCL] Comment détecter une combinaison de touches ?
    Par micatmidog dans le forum Composants VCL
    Réponses: 3
    Dernier message: 23/01/2005, 14h19

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo