2009-09-02 8 views
0

Tout d'abord, j'aimerais noter que j'ai besoin d'utiliser les API COM/OLE2, les éléments de bas niveau, ce que vous pouvez mettre dans un programme de console Windows C. Je ne peux pas utiliser MFC. Je ne peux pas utiliser .NET.Reconnexion au processus démarré via COM

Ma question est:

Vu le code suivant:

CLSID clsid;  
HRESULT hr; 

hr = CLSIDFromProgID(L"InternetExplorer.Application", &clsid); 
assert(SUCCEEDED(hr)); 

hr = CoCreateInstance(clsid, 
         NULL, 
         CLSCTX_LOCAL_SERVER, 
         IID_IDispatch, 
         (void **)&(iePtr_)); 
assert(SUCCEEDED(hr)); 

Est-il possible d'écrire des informations sur le disque afin que je puisse se reconnecter à la même instance de IE plus tard ? Fondamentalement, "iePtr_" peut-il être stringifié pour une reconstitution ultérieure par un autre processus?

Merci.

---- ------ a ajouté plus tard

Le problème plus large, je suis en train de résoudre est que je veux démarrer une application AutoCAD, charger des données dans, puis le laisser tourner mon client à interagir avec. Plus tard, il retournera à mon application et je veux me reconnecter à la même session AutoCAD et lui fournir plus de données.

Maintenant, je me rends compte que je peux garder le pointeur IDispatch en mémoire dans mon application et que je pourrai continuer à interagir avec le même processus AutoCAD. C'est ma position de repli. Cependant, j'utilise un programme "wrapper" pour faire mes trucs COM. Donc, l'emballage est transitoire. Mon application principale démarre l'encapsuleur, puis l'encapsuleur communique, puis quitte. Je veux juste que les processus de wrapper suivants puissent se reconnecter au même processus AutoCAD.

Pourquoi utiliser un emballage? Voici la raison de travail: Mon application principale est une application 32 bits, mais je peux utiliser un wrapper 64 bits et communiquer avec AutoCAD 64 bits. Je dois pouvoir communiquer avec AutoCAD 64 bits et ne peux probablement pas facilement transférer mon application principale (500K + lignes de C++) par rapport à mon programme wrapper (quelques centaines de lignes).

+0

Quel est le problème plus large que vous essayez de résoudre? – reuben

+0

Vous devez utiliser SUCCEEDED() au lieu de! FAILED() - c'est ce à quoi il est destiné. Je vais éditer le code. – sharptooth

+0

Ajout d'images "plus larges" au message principal. –

Répondre

0

Si l'application s'est enregistrée dans la table des objets en cours d'exécution, vous pouvez utiliser la fonction GetActiveObject pour obtenir une référence à l'objet d'application.

IUnknown *pUnknown; 

hr = GetActiveObject(clsid, NULL, &pUnknown); 
assert(SUCCEEDED(hr)); 

hr = pUnknown->QueryInterface(IID_IDispatch, (void **)&(iePtr_)); 
assert(SUCCEEDED(hr)); 
-1

Non, c'est impossible. L'idée de COM est que le serveur COM est démarré de manière transparente et ne conserve l'état que lorsque vous avez cessé d'utiliser ses objets. Après avoir libéré les objets COM, le sous-système COM est libre d'arrêter complètement le serveur et il n'y a aucun moyen de recréer le même processus. La seule façon dont un résultat similaire serait possible est d'avoir un objet COM avec des méthodes de sérialisation qui permettrait de sauvegarder l'état dans un flux et de le restaurer à partir d'un flux. Mais même alors, vous devrez à nouveau CoCreateInstance(), obtenir un nouveau pointeur d'interface d'objet COM et appeler la méthode de restauration de cet objet.

Le pointeur que vous obtenez de CoCreateInstance n'est valide que pour le processus en cours, si vous l'enregistrez sur le disque et le restaurez plus tard, il deviendra invalide.

+0

Cela semble une vue plutôt naïve/pure de COM - peut-être que le monde serait un meilleur endroit si le vrai code COM ne se comportait que de cette façon. – morechilli

+0

@morechilli: C'est le comportement impliqué par le modèle. Bien sûr, la mise en œuvre fait ce qu'elle fait. – sharptooth

0

CoMarshalInterface (et les API associées) peuvent être utilisées pour assembler une interface dans un autre thread, processus ou PC différent sur le réseau. Je ne sais pas combien de temps vous êtes autorisé à attendre avant de terminer le processus de marshaling, mais en principe, si l'objet pour lequel vous marshaling une interface n'a pas été fermé, le processus de marshaling peut être complété plus tard. Etre capable de détruire un objet OLE et de restaurer plus tard "le même objet" est lié à ce que l'on appelle des Monikers, et si vous le pouvez (peut) comprendre, alors votre Juju OLE/COM est vraiment puissant.

+0

Apparemment, DCOM dispose d'un mécanisme de "garbage collection" qui tue le talon pour un objet après 4 minutes, donc c'est un timeout à prendre en compte. Pourvu que l'objet soit hébergé dans son propre processus, vous devriez être en mesure de rassembler l'interface ptr dans un flux, de l'écrire sur le disque, puis de le reconstituer dans un autre processus, si seulement vous le faites dans ces 4 minutes. –

0

Je suggère de faire la couche d'emballage longue durée de vie plutôt que transitoire, par conséquent, il peut facilement contenir une seule référence à la troisième application.

L'encapsuleur peut toujours apparaître transitoire au code client. Si vous faites de l'encapsuleur un singleton COM, chaque fois que vous le co-créez, vous retrouverez la même instance.

Pour garantir la durée de vie du wrapper pendant la durée de vie de votre client, maintenez une référence du démarrage à l'arrêt. Cette référence n'a pas besoin d'être connectée à un autre code. Tout autre code crée simplement le singleton chaque fois qu'il le veut.

Questions connexes