2011-01-14 15 views
5

Tengo un servidor COM fuera de proceso que necesita vigilar las cosas. Este servidor se ejecuta como un servicio y, internamente, es un singleton. Por simplicidad, lo llamaré BossCom.¿Cómo puedo ordenar una referencia COM fuera de proceso a través de los límites del proceso?

Tengo otro servidor COM fuera de proceso que es un trabajador. Es, para la estabilidad del sistema, un servidor de un solo uso (lo que significa que si crea 2 WorkerCom, hay 2 WorkerCom.exe en ejecución). Por simplicidad, lo llamaré WorkerCom.

WorkerCom puede iniciarse por cualquier cosa, incluso por sí mismo si alguien lo ejecuta a través de la línea de comandos con los argumentos correctos de la línea de comando.

El objetivo general es que BossCom sepa qué son los WorkerComs, sepa lo que están haciendo y sea capaz de darles órdenes (pausar, detener, acelerar, etc.).

Mi primer pensamiento en esto sería que cada vez que WorkerCom comienza, él CoCreateInstance a BossCom y llama a BossCom-> RegisterWorker (IUnknown me). Luego, cuando el WorkerCom esté a punto de apagarse, llamaría a BossCom-> UnregisterWorker (No me conocía). BossCom podría QueryInterface the IUnknown para IWorkerCom y poder emitir comandos.

Eso funcionaría muy bien si todos estos objetos com estuvieran en el mismo proceso, pero no es así. Pensé en usar GlobalInterfaceTable, pero solo es global en el sentido de un solo proceso.

He pasado unos días investigando esto y estoy perdido. Tal vez estoy con visión de túnel.

¿Cómo puedo obtener una referencia a un objeto com del Worker to the Boss?

Ah, y, por lo que vale, BossCom está escrito en C# y WorkerCom está escrito en ATL C++, pero tomaré las soluciones escritas en VB, Scala, Lisp o cualquier otra cosa. Me imagino que puedo traducir la idea central. :-)

+3

¿Esto no sólo el trabajo? Admito que no he hecho mucho con COM, pero el hecho de que esté fuera de proceso es que ya está logrando que COM coordine las llamadas a través de los límites del proceso, ¿no es así? –

+0

Correcto, para la mayoría de las cosas, pero IUnknown es solo un puntero, ¿verdad? El puntero "this" en WorkerCom no tendrá ningún significado en BossCom, ¿verdad? O el proceso de clasificación mantendrá el significado. Supongo que al menos debería intentarlo. –

+2

Debería funcionar fuera de la plataforma dado que hay proxy/stubs o typelib para facilitar la clasificación. De hecho, el marshalling es exactamente para eso, para darle a un cliente un objeto falso ("proxy") que se refleja en el servidor. Funciona de forma transparente desde la perspectiva del código. – sharptooth

Respuesta

2

Según los comentarios, esto realmente funciona de la caja. Sin embargo, hay un detalle adicional que lo hace funcionar.

Originalmente cuando estaba mirando interfaces C# que trataban con las interfaces de copia, el tipo de argumento era IntPtr. Bueno, un IntPtr es solo un largo, por lo que transfiere el valor como está y, como tal, no funciona.

La clave es establecer el atributo MarshalAs en el argumento. Entonces mi método de RegisterWorker se ve así:

public void RegisterWorker(
     [In, MarshalAs(UnmanagedType.IUnknown)] object ptr 
     ) 
    { 
     IWorkerCom worker = (IWorkerCom) ptr; 
     Workers.Add(worker); 
    } 

Increíblemente increíble.

1

Tuve que hacer algo similar recientemente y descubrí que el uso de la memoria compartida funcionaba muy bien para mí. El BossCom podría crear y poseer la memoria compartida y los trabajadores podrían registrarse haciendo una entrada en la memoria compartida. Aquí hay un MSDN link de lo que estoy hablando. Recuerde utilizar un mutex para sincronizar el acceso a la memoria ...

+0

Eso maneja bien el registro, pero no estoy seguro de cómo eso ayuda con el comando y control de los trabajadores. –

+0

La memoria compartida es simplemente una forma de comunicarse a través de un bloc de notas. El BossCom podría escribir los comandos en la memoria y señalar un evento que los trabajadores esperan. Hay muchas otras maneras de hacerlo y todo depende de sus requisitos de seguridad. Acabo de encontrar este enfoque muy rápido de implementar y muy flexible. – T33C

+0

Aprecio la idea, pero UAC lo hace más difícil. Mi aplicación debe ejecutarse en Windows XP y versiones posteriores. Las API que hacen que la memoria compartida se pueda utilizar a través de los límites de usuarios de UAC no existen en XP. He trabajado en esto en el pasado, pero no estoy ansioso por hacerlo de nuevo. –

1

Tiene limitaciones para poder crear interfaces escalable en C#. No es una forma fácil de configurar el proxy. No hay tal problema en ATL, declara una interfaz de devolución de llamada en el IDL. Y pase un puntero de instancia con la llamada RegisterWorker(). El servidor debe almacenarlo hasta que obtenga la llamada para anular el registro. Usa esa interfaz de devolución de llamada para generar notificaciones.

2

Debe echar un vistazo a Monikers, que se utilizan para identificar una instancia de objeto COM incluso en diferentes máquinas.

+0

Esto es interesante. Y potencialmente hará que otras partes de mi proyecto sean más fáciles. Recuerdo haber trabajado con DirectShow, los monikers solo eran cadenas de texto. Esos deben ser extremadamente fáciles. Demonios, incluso podría ponerlos en una mesa ESE para que cualquiera (como otros trabajadores) pueda encontrarlos. Una búsqueda rápida no mostró cómo puedo crear un apodo para mi objeto. ¿Alguna sugerencia? –

+0

¿Tal vez CreateObjrefMoniker? –

Cuestiones relacionadas