c# .net winforms activex

c# - Control ActiveX sin formulario.



.net winforms (4)

Mi solución es crear una forma de victoria oculta que aloje el control activex

Estamos obligados a utilizar un control ActiveX de terceros.

El único problema es que la capa de nuestro software es una capa empresarial y no tiene acceso a una ventana o formulario. También se ejecuta en subprocesos separados (y debería funcionar desde cualquier subproceso) que no sean STA.

En lugar de romper nuestra separación de UI de la lógica empresarial, utilizamos esta solución para que funcione:

Thread thread = new Thread((ThreadStart) delegate { _myActiveX = new MyActiveXType(); _myActiveX.CreateControl(); //more initialize work Application.Run(); }); thread.SetApartmentState(ApartmentState.STA); thread.IsBackground = true; thread.Start();

Luego, en cualquier momento en que necesitemos hacer referencia al control, llamamos _myActiveX.BeginInvoke() o Invoke() .

Al eliminar esta clase (salir de nuestra aplicación), disponemos del control y abortamos el hilo.

Mi pregunta es, ¿hay algún problema con esto? ¿Hay una mejor manera de manejar esto?

¿Existe una mejor forma integrada de trabajar con un control ActiveX desde un entorno de subprocesos múltiples desconocido? Estamos tratando de escribir nuestra clase de una manera que envuelva el control pero que funcione desde cualquier hilo.

ACTUALIZACIÓN: Como se sugirió una respuesta, realmente preferiríamos usar el objeto COM estándar y no usar un control en absoluto. Nuestro problema con eso fue que obtendríamos el error "(Excepción de HRESULT: 0x8000FFFF (E_UNEXPECTED)" en el primer método o propiedad que llamamos en el objeto COM. Este es un error bastante genérico que no obtenemos al usar ActiveX , ¿algunas ideas?

ACTUALIZACIÓN: Nuestro ocx es "CX25.ocx", utilizando tlbimp.exe obtenemos CX25Lib.dll. Usando aximp.exe, obtenemos AxCX25Lib.dll y CX25Lib.dll. CX25Lib.dll no funciona en ninguno de los casos. AxCX25Lib.dll funciona.


Sé que este es un post antiguo, pero recomendaría usar el TPL en nuestra era moderna.

Es mejor usar la biblioteca paralela de tareas en lugar de la API de subprocesamiento anterior debido a las características del manejo de excepciones, la cancelación, la continuación y la devolución de resultados.

Aquí hay un ejemplo:

using (var sta = new StaTaskScheduler(1)) { var taskResult = await Task.Factory.StartNew(() => { var results = new List<ResultType>(); using (var ax = new MyActiveXType()) { // important to call this just after constructing ActiveX type ax.CreateControl(); ax.SomeIterativeEvent += (s, e) => results.Add(e.SomeThing); // if applicable, you can tear down the message pump ax.SomeFinalEvent += (s, e) => Application.ExitThread(); //more initialize work // start message pump Application.Run(); return results; } }, CancellationToken.None, TaskCreationOptions.None, sta); return taskResult; }

Algunos puntos:

  1. StaTaskScheduler es un tipo que se encuentra en el paquete de nuget ParallelExtensionsExtras . Necesitará esto para programar tareas para ejecutar en un apartamento de un solo hilo.

  2. Le paso 1 al constructor de StaTaskScheduler para que solo cree un solo hilo para mí.

  3. Se llama a Application.ExitThread() para detener el bombeo del mensaje, que a su vez permite que la ejecución pase por Application.Run() para que se pueda devolver algún resultado al llamante.


Si llama al control ActiveX desde una capa empresarial, eso significa que debe poder usarse sin una interfaz de usuario, por ejemplo, llamando a sus métodos públicos. ¿Por qué no solo crear un RCW de interoperabilidad para la clase de control ActiveX y llamar directamente a sus métodos?


Supongo que esta es la forma correcta de hacerlo.

Hemos estado utilizando mi código anterior en entornos de prueba durante las últimas semanas sin problemas.

Si alguien tiene que usar un ActiveX sin un formulario, asumo que esta es una forma de hacerlo.

Solo asegúrese de llamar a _yourActiveXControl.CreateControl () directamente después del constructor de su objeto ActiveX. Esto simplificó muchos problemas que teníamos originalmente.