Pregunta

Sé que podemos usar CoLoadLibrary y DllGetClassObject para obtener la interfaz IClassFactory y la interfaz del componente COM sin registrar la DLL.

Pero ¿qué pasa con un componente COM en un EXE?¿Hay alguna manera de obtener una interfaz de componente COM desde un servidor COM de tipo EXE simplemente proporcionando una ruta de archivo diferente?

¿Fue útil?

Solución

Si usa el real Registro gratuito com, debería poder obtener este trabajo tanto para los objetos de PROC como para Out-Proc.

A medida que se apunta a Sharptooth, realmente no estás usando COM GRATIS de registro.En su lugar, realmente estás rodando tu propio fingir las llamadas que us usa durante la activación.Su solución puede funcionar si controla su aplicación y el servidor COM que está activando, pero es probable que falle lo contrario.

Otros consejos

No, no puedes.Necesita la configuración de COM entre su programa y el servidor COM fuera de proceso.Para lograrlo hay que llamar CoInitialize() y luego cualquiera CoCreateInstance() o CoGetClassObject().

La ruta que describe con un servidor en proceso: llamar CoLoadLibrary() y luego DllGetClassObject() - es de hecho un truco sucio: pasa por alto los mecanismos COM normales y, por lo tanto, por ejemplo, no se activará ninguna clasificación incluso si es necesaria para satisfacer los requisitos del modelo de subprocesamiento (cosas STA/MTA).Este tipo de truco sucio es posible porque un servidor en proceso es una DLL normal con varias funciones conocidas expuestas.Lo mismo es imposible para un servidor COM fuera de proceso; en ese caso, debe confiar en COM.

Puede pasar un componente COM en una llamada de función, como un puntero.

Entonces, supongamos que implementa un objeto en su EXE y eso carga otro objeto COM desde una DLL, puede pasar el objeto basado en EXE al objeto desde la DLL.El objeto cargado debería admitir una interfaz que tenga una función que acepte un puntero, p.

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

Si el objeto basado en DLL implementa eso, puede llamarlo desde su EXE y pasarle un objeto que no esta registrado en ningun lado, por lo que no es necesario registrar objetos en un EXE para lograrlo.

Los únicos requisitos son la correcta implementación de IUnknown:No destruyas el objeto hasta Release ha sido llamado el número correcto de veces y asegúrese de que QueryInterface se puede utilizar para atravesar entre un conjunto fijo de interfaces en el objeto y la consulta de IUnknown siempre devuelve la misma dirección.

Por otro lado, puedes registrar un EXE como servidor de objetos, pero eso introduce mucha complejidad;COM tiene que iniciar la ejecución del EXE y luego enviarle mensajes a través de la cola de mensajes de Windows.Esto sólo se usa ampliamente para OLE;puede ser bastante frágil.

Actualizar

Una solución más completa es definir una forma estándar de crear una instancia de un tipo de objeto, pero permitir que el EXE defina cómo funciona.El EXE implementaría:

interface IComponent;

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

Cada componente debe soportar esta interfaz:

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

Ahora, para obtener el comportamiento estándar en el que el EXE quiere usar el registro para buscar componentes, puede implementar el CreateInstance método como este:

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;
}

Pero, por supuesto, puede cambiar esto e "inyectar" algunos componentes.Entonces, en lugar del registro (o además de él), se puede utilizar un archivo de configuración.O (como ha preguntado) el EXE podría tener implementaciones integradas de algunos componentes:

Debido a que cada componente recibe una notificación del entorno cuando se crea, puede utilizar el entorno para crear más componentes:

// 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...

Entonces, cada vez que se crea un componente, el entorno (definido en el EXE) puede controlar exactamente cómo se encuentra la implementación del componente.Cada creación pasa por el EXE.

A esto a veces se le llama "inyección de dependencia" o "inversión de control".

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top