L'enregistrement est libre d'activation possible par EXE (out-of-process) COM serveurs?

StackOverflow https://stackoverflow.com/questions/3211345

  •  13-09-2020
  •  | 
  •  

Question

Je sais que nous pouvons utiliser CoLoadLibrary et DllGetClassObject pour obtenir de l'interface IClassFactory et obtenir le composant COM interface sans enregistrement de la DLL.

Mais que penser d'un composant COM dans un EXE?Est-il possible que je peux obtenir un composant COM interface à partir d'un fichier EXE de type serveur COM en fournissant simplement un autre chemin d'accès au fichier?

Était-ce utile?

La solution

Si vous utilisez le réel INSCRIPTION FREE, vous devriez être en mesure d'obtenir ce travail pour des objets COMPR et Out-of-Proc.

Comme Sharpoth a souligné, vous n'utilisez vraiment pas l'enregistrement gratuit.Au lieu de cela, vous roulez vraiment le vôtre en faisant semblant des appels utilisés lors de l'activation.Votre solution peut fonctionner si vous contrôlez votre application et le serveur COM que vous activez, mais il risque d'échouer autrement.

Autres conseils

Non, vous ne pouvez pas.Vous avez besoin de COM le programme d'installation de triage entre votre programme et proc serveur COM.Pour ce faire, vous devez appeler CoInitialize() et puis CoCreateInstance() ou CoGetClassObject().

Le chemin que vous décrivez avec un serveur in-process - appel CoLoadLibrary() et puis DllGetClassObject() est en fait une sale hack - elle court-circuite COM normal des mécanismes et donc, par exemple, aucun regroupement donnera le coup, même si elle est nécessaire pour satisfaire le modèle de threading exigences (STA/MTA genre de trucs).Ces sales hack est possible parce qu'un serveur in-process est une DLL normale avec plusieurs fonctions exposées.La même chose est impossible pour un proc serveur COM - vous besoin de s'appuyer sur COM dans ce cas.

Vous pouvez passer d'un composant COM dans un appel de fonction, comme un pointeur.

Supposons donc que vous mettre en œuvre un objet dans votre EXE, et qui charge un autre objet COM à partir d'une DLL, vous pouvez passer l'EXE en fonction de l'objet à l'objet à partir de la DLL.L'objet chargé aurait besoin pour soutenir une interface qui a une fonction qui accepte un pointeur, par exemple

interface ILoadedObject
{
    HRESULT GiveObject(IUnknown *pObj);
};

Si la DLL objet implémente que, vous pouvez l'appeler à partir de votre fichier EXE et passer un objet qui n'est pas enregistré n'importe où, il n'est donc pas besoin d'enregistrer des objets dans un fichier EXE pour atteindre cet objectif.

Les seules exigences sont sur la bonne mise en œuvre de IUnknown:de ne pas détruire l'objet, jusqu'à ce Release a été appelé le bon nombre de fois, et de s'assurer que QueryInterface peut être utilisée pour parcourir entre un ensemble fixe d'interfaces sur l'objet et que l'interrogation de l' IUnknown renvoie toujours à la même adresse.

D'autre part, vous pouvez enregistrer un fichier EXE en tant que serveur d'objets, mais qui présente beaucoup de complexité;COM a pour lancer l'EXE en cours d'exécution, puis envoyer des messages via le Windows file d'attente de messages.Ce n'est largement utilisé pour OLE;il peut être assez fragile.

Mise à jour

Une solution plus complète est de définir une méthode standard pour créer une instance d'un type d'objet, mais de permettre l'EXE pour définir la façon dont il fonctionne.L'EXE serait de mettre en œuvre:

interface IComponent;

interface IEnvironment : IUnknown
{
    HRESULT CreateInstance(REFCLSID clsid, IComponent **ppNew);
}

Chaque composant doit prendre en charge cette interface:

interface IComponent : IUnknown
{
    HRESULT SetEnvironment(IEnvironment *pEnv);
}

Maintenant, pour obtenir un comportement où l'EXE veut utiliser le registre pour trouver des composants, il peut mettre en œuvre la CreateInstance méthode comme ceci:

HRESULT Env::CreateInstance(REFCLSID clsid, IComponent **ppNew)
{
    HRESULT hr = CoCreateInstance(clsid, NULL, CLSCTX_INPROC_SERVER,
                     __uuidof(IComponent), (void **)&ppNew);
    if (FAILED(hr))
        return hr;

    (*ppNew)->SetEnvironment(this);
    return S_OK;
}

Mais bien sûr, il peut modifier cette situation et à "injecter" de certains composants.Ainsi, au lieu de (ou en plus) de la base de registre, un fichier de configuration peut être utilisé.Ou (comme vous l'avez demandé) l'EXE pourrait avoir intégré dans les implémentations de certains composants:

Parce que chaque composant est notifié de l'environnement lorsqu'il est créé, il peut utiliser l'environnement pour créer d'autres composants:

// inside some component:
HRESULT Comp::SetEnvironment(IEnvironment *e)
{
    m_env = e; // using a smart pointer for ref-counting
    return S_OK;
}

// in some method of the component

ComPtr<IComponent> button;
m_env->CreateInstance(CLSID_Button, &button);

// now query button for more useful interface...

Donc, chaque fois qu'un composant est créée, l'environnement (défini dans le fichier EXE) pouvez contrôler exactement comment la mise en œuvre de la composante est trouvé.Chaque création se passe via le fichier EXE.

Cela est parfois appelé "l'injection de dépendance" ou "inversion de contrôle".

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top