2009-05-27 15 views
7

El VB6 help on GetObject dice "No se puede usar GetObject para obtener una referencia a una clase creada con Visual Basic" (¡la última oración!). Mi GUI VB6 expone objetos como un exe ActiveX, para que otros componentes los manipulen. Quiero que los otros componentes se conecten a la GUI que ya se está ejecutando, en lugar de iniciar una nueva instancia del exe. He encontrado utilizando GetObject funciona, si se utiliza esta sintaxis:GetObject y VB6 ActiveX exe

Set myobj = GetObject("", "ProjectName.ClassName") 

Me preocupa que la ayuda dice que esto no debería funcionar, aunque he hecho un poco de prueba y no he encontrado ninguna problemas hasta ahora. ¿Algún experto COM por ahí que pueda decirme si voy a tener problemas en el futuro? ¿Y estaría bien con CreateObject de todos modos?

La configuración de ActiveX exe es: grupo de subprocesos con un solo subproceso. La clase tiene instancias MultiUse. Es posible que estas configuraciones sean suficientes para evitar que CreateObject inicie una nueva instancia del exe de todos modos. ¿Es eso correcto?

Respuesta

7

La documentación es confusa, pero correcta. La página de MSDN se hace referencia ayuda a explicar por qué su llamada GetObject no lanza un error:

If pathname [the first argument] is a zero-length string (""), GetObject returns a new object instance of the specified type. If the pathname argument is omitted, GetObject returns a currently active object of the specified type. If no object of the specified type exists, an error occurs.

Es sutil, pero la implicación es que

GetObject "", "ProjectName.ClassName 

es en realidad equivalente a

CreateObject "ProjectName.ClassName" 

Es decir, pasar una cadena vacía al primer parámetro de GetObject hace que funcione exactamente como CreateObject, lo que significa que creará una nueva instancia de la clase, en lugar de devolver una referencia a una instancia que ya se está ejecutando.

Volviendo al extracto de MSDN, menciona que omitir el primer argumento en GetObject hará que GetObject devuelva una referencia a una instancia que ya se está ejecutando, si existe. una llamada de este tipo se vería así:

GetObject , "ProjectName.ClassName" 'Note nothing at all is passed for the first argument' 

Sin embargo, si intenta hacer esto, obtendrá inmediatamente un error en tiempo de ejecución. Este es el caso de uso al que hace referencia la documentación cuando dice que GetObject no funciona con las clases creadas con VB6.

La razón por la que esto no funciona es debido a cómo GetObject realiza su magia. Cuando se omite el primer parámetro, intenta devolver una instancia de objeto existente consultando la Tabla de objetos en ejecución (ROT), una tabla de búsqueda en toda la máquina que contiene objetos COM en ejecución. El problema es que los objetos deben registrarse explícitamente en la Tabla de Objetos en ejecución por el proceso que los crea para poder acceder a otros procesos: el tiempo de ejecución de VB6 no registra clases EXE de ActiveX en el ROT, por lo que GetObject no tiene forma de recuperar una referencia a una instancia que ya se está ejecutando.

+0

respuesta perfecta, gracias. ¡Siempre le digo a la gente RT * M así que esto es una prueba de mi propia medicina! GetObject ("ProjectName.ClassName) provoca el error 429, 'El componente ActiveX no puede crear el objeto'. Supongo que es en realidad mi proyecto y configuración de la clase que están impidiendo que varias instancias del archivo EXE que se creen. – MarkJ

2

I want the other components to connect to the GUI that's already running, rather than start a new instance of the exe.

El truco es recordar que en un EXE de ActiveX se puede configurar para que solo haya una instancia de la BIBLIOTECA ejecutándose. Es correcto que no puede alcanzar y simplemente arrancar una instancia determinada de una clase a través del límite del proceso. Sin embargo, el EXE de ActiveX se puede configurar para que cualquier instancia de clases pueda acceder a las variables de GLOBAL.

Cómo hacer exactamente esto se pone un poco complejo.Puede usar un EXE de ActiveX como un EXE normal, la diferencia principal es que TIENE que usar Sub Main. También puede verificar si funciona de manera independiente o no. Ahora estoy asumiendo que este es el caso con la aplicación de MarkJ.

Si este es el caso, lo que necesita es crear una clase de aplicación y configurarla para que cuando se cree (utilizando Class_Initialize) se rellene con las instancias actuales de formularios y colecciones.

recomiendo encarecidamente crear una DLL de ActiveX (no EXE) que no tiene nada pero las clases a implementarse como interfaces. En lugar de ir pasando

'Class ThisGUIApp 
Public MainForm as Form 

Se crea una interfaz que tiene todas las propiedades y métodos necesarios para acceder a los elementos del formulario principal. Después de ir

'Class ThisGUIApp 
Public MainForm as IMainForm 

Private Sub Class_Initialize 
    Set MainForm = frmMyMainForm 
End Sub 

'Form frmMyMainForm 
Implements IMainForm 

Esto se hace porque si bien puede enviar un formulario a través de proceso de aplicación cosas se tambalean cuando intenta acceder a ella los miembros y los controles. Si asignó a través de una interfaz, la conexión es mucho más sólida. Además, documenta mejor el tipo de cosas que intenta hacer.

+0

1. La configuración exe ActiveX son grupo de subprocesos con sólo un hilo, y la clase ha de instancias bien multiuso. creo que esto significa sólo una instancia nunca se ejecuta. no paso formularios o controles a través del límite del proceso, eso es definitivamente escamosa. – MarkJ

+0

Usted puede con formas siempre que tenga la forma de implementar una interfaz en cuyo caso se trata como un objeto ActiveX. Lo hice durante años. –