Visual Basic.NET - Problemas instanciando clase de una DLL

 
Vista:

Problemas instanciando clase de una DLL

Publicado por David (5 intervenciones) el 16/07/2009 00:26:47
Hola, estoy implementando una DLL en VB.NET y una aplicacion sencilla desde donde instancio una clase de esta DLL. Me explico más detalladamente:

Por un lado tengo mi DLL en VB.NET (proyecto Modulo) con una única clase CComunicacion.vb que contiene un par de funciones y procedimientos. En esta DLL referencio otra DLL hecha en Visual Basic (utiles.dll), e instancio un par de objetos de una clase de dicha dll:

Public Class CComunicacion
Public ParamIn As New Utiles.CParametro
Public ParamOut As New Utiles.CParametro

Hasta aquí ningún problema, esto compila y no da ningún fallo.

El problema viene al intentar instanciar la clase CComunicacion de mi DLL. Necesito que la aplicación la instancia dinamicamente, ya que debe poder instanciar tanto la clase de mi DLL como las de otras DLL. Es decir, en un textbox yo poner "miDLL.CComunicacion" y se instancie esa clase (o algo similar).

He probado varias cosas, pero no funciona ninguna de ellas. Al principio (cuando mi DLL apenas hacia nada) funcionaba simplemente con esto:

Dim clase As Object
clase = CreateObject(txtClase.Text) '------------->>siendo esto el textbox que comentaba antes

La excepcion es: "No se puede crear el componente ActiveX."

Agradecería que alguien me ayudase con este tema, indicandome como debo hacerlo, si debo copiar el archivo de mi DLL en el otro proyecto, o cualquier cosa necesaria. Lo que no entiendo es que al principio si me funcionaba (estaba haciendolo en VS2008), pero tuve que cambiar a VS2005 por exigencias del proyecto y ya no consigo que funcione ni en uno ni en otro, igual antes hacia algo que ahora no, no se.

Muchas gracias por adelantado! Espero vuestra ayuda, ya que no puedo ni depurar mi DLL al no poder probarlo.
Valora esta pregunta
Me gusta: Está pregunta es útil y esta claraNo me gusta: Está pregunta no esta clara o no es útil
0
Responder
sin imagen de perfil

RE:Problemas instanciando clase de una DLL

Publicado por Joan F (129 intervenciones) el 18/07/2009 07:46:42
Hola,

Las librerías DLL generadas en .NET no tienen interoperabilidad COM implícita, de forma que no pueden ser llamadas como objetos ActiveX mediante CreateObject.

Para el problema que tienes, habría dos formas de proceder:

1-Crear explícitamente una interface COM en la DLL, de esta forma se puede llamar como un componente ActiveX. Para esto hay esta pagina: http://www.elguille.info/NET/servidorNETparaCOM/formulario_NET_desde_VB6.htm

2-Cargar dinámicamente la librería dll generada en .NET (assembly). Esto seria algo así:

Dim libreria As System.Reflection.Assembly
Dim objetodinamico As Object

libreria = System.Reflection.Assembly.LoadFile("archivoDLL")

objetodinamico = libreria.CreateInstance("miDLL.CComunicacion")
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
0
Comentar

RE:Problemas instanciando clase de una DLL

Publicado por David (5 intervenciones) el 19/07/2009 01:31:13
Hola,

gracias por tu respuesta.

He probado la segunda opción, ya que me interesa más poder cargar dinámicamente distintas DLL (la mia y otras), que unicamente la mia. Sin embargo, no he conseguido que funcione. El error que daba anteriormene no lo da, pero cuando voy a llamar a alguno de los métodos que tengo en mi DLL da error, ya que no ha creado bien el objeto dinámico, se queda con valor Nothing.

De hecho, da igual que ponga miDLL.CComunicacion, que cualquier otra cosa, el fallo es el mismo.

¿alguna idea?

Gracias.
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
0
Comentar
sin imagen de perfil

RE:Problemas instanciando clase de una DLL

Publicado por Joan F (129 intervenciones) el 19/07/2009 06:08:07
En el metodo CreateInstance, tienes que poner la cadena del tipo que vas a crear completa (incluyendo el namespace). Si el .NET no encuentra un objeto cuyo tipo coincide con la cadena que le indicas devuelve un nothing.

En todo caso, si no sabes el tipo concreto del objeto, el objeto assembly contiene el método GetTypes que devuelve un array con los tipos disponibles en el ensamblado o DLL. Puedes examinar el array para encontrar el nombre completo del objeto que quieres crear.

También puedes probar con el método Activator.CreateInstance, pasando como parámetros la ruta del ensamblado y la cadena del tipo que quieres crear.
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
0
Comentar

RE:Problemas instanciando clase de una DLL

Publicado por David (5 intervenciones) el 19/07/2009 12:53:31
Bueno antes de nada, muchas gracias por la ayuda que me estas dando!

He probado a ver los tipos con el método GetTypes como me decias, pero ahora en lugar de devolver Nothing da una excepcion al poner el full name que devuelve el metodo GetTypes (se corresponde con el namespace.clase).

El código es algo así:

libreria = System.Reflection.Assembly.LoadFile(txtDLL.Text)

Dim tipos() As System.Type
tipos = libreria.GetTypes()

clase = libreria.CreateInstance("ModuloCom.CComunicacion")

La excepcion es:

No se controló System.Reflection.TargetInvocationException
Message="Se produjo una excepción en el destino de la invocación."


No se que hacer para solucionar esto, y no puedo probar mi DLL para saber si hace lo que debe o no sin solucionar este problema antes. No debería ser tan complicado usar una DLL propia en una aplicación no? Siendo ambas cosas en VB.NET.

Gracias por adelantado.
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
0
Comentar
sin imagen de perfil

RE:Problemas instanciando clase de una DLL

Publicado por Joan F (129 intervenciones) el 19/07/2009 18:34:16
La excepción System.Reflection.TargetInvocationException indica que se ha producido un error al llamar al objeto, o sea, que al crear el objeto "ModuloCom.CComunicacion" o bien al llamar a uno de sus métodos se ha producido un error. Si no llamas a ningún método de la clase, quizás el error este en el constructor o haya algun problema en la DLL.

En todo caso, si capturas la excepción con un try - catch, en la propiedad InnerException de la excepción te indica la excepción que se ha producido en el código llamado mediante reflection.

A ver. Para usar DLL propias en una aplicación, lo normal es añadirlas como referencia a la aplicación, mediante proyecto -> agregar referencia, entonces, el Visual Studio se encarga de todo y puedes crear objetos directamente en el código. Por las indicaciones que me das, creo que lo que estas tratando de hacer es cargar una DLL dinámicamente en tiempo de ejecución. Esto ya es algo bastante más complejo. No solo a nivel de código, ya que trabajar con reflection es complejo, sino que la depuración de código o el control de errores en clases invocadas puede dar muchos quebraderos de cabeza.

Si me puedes indicar que estas intentando hacer quizás te pueda dar mas ayuda. Pero mi recomendación, seria añadir la DLL en la que estas trabajando como referencia mediante el .NET, y una vez terminada y revisada entonces realizar las modificaciones para llamarla dinámicamente.
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
0
Comentar

RE:Problemas instanciando clase de una DLL

Publicado por David (5 intervenciones) el 19/07/2009 20:42:02
Hola de nuevo,

Vaya, ni siquiera lo consigo hacer funcionar agregando la referencia a mi DLL al proyecto.

Te explico:

Parto de una DLL (hecha en VB6 creo, no es mia): util.dll

Yo he hecho en VB.NET mi DLL en la que tengo un par de variables del tipo CParametro incluido en la DLL util.dll. (Esta DLL la tengo como referencia en el proyecto sin problema).

Tengo luego la aplicación en VB.NET desde la que necesito utilizar tanto un método de mi DLL como sus variables (del tipo CParametro de la otra DLL no mia). Esto debo hacerlo dinámicamente preferiblemente para que se puedan utilizar otras DLL similares a la mia más adelante.

Agregando la referencia al proyecto de mi DLL lo hago si la selecciono en Examinar (aparece tb en COM, pero esa da error). El problema es que al ejecutar la aplicación falla porque falta agregar una referencia a la primera DLL, a la util.dll por las variables de mi DLL. Y esto no me deja hacerlo. Si la selecciono en Examinar dice que me asegure de que se tiene acceso (esta en la misma carpeta) y que es un componente COM válido.

Sigo sin encontrar solución al problema...

Gracias de nuevo por tu ayuda!! Si necesitas que te aclare algo más dimelo.
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
0
Comentar
sin imagen de perfil

RE:Problemas instanciando clase de una DLL

Publicado por Joan F (129 intervenciones) el 20/07/2009 05:49:59
Por lo que me explicas, yo empezaría por comprobar que utils.dll funciona correctamente. Primero crea una pequeña aplicación windows, prueba de añadir la referencia como referencia COM a utils.dll y comprueba que sus métodos funcionan correctamente llamando desde COM.

Si utils.dll no se puede añadir como referencia COM, o bien te da un error, es que utils.dll no es una DLL con automatizacion COM o ActiveX (no ha estado hecha en VB6, puede en C, C++ o otros), y sus métodos han de ser invocados mediante PInvoke. Esto es bastante complejo (puedes hacerte una idea en http://www.elguille.info/NET/revistas/dotNetmania/pdf/dotnetmania_23_pag_35_40.pdf. A pesar que el código esta en C# se entiende perfectamente y aunque trata específicamente sobre la API de windows, sirve para cualquier DLL no administrada). Si no te queda claro que es todo esto de COM/PInvoke/... te recomiendo que eches un vistazo a http://www.elguille.info/NET/revistas/dotNetmania/pdf/dotnetmania_22_pag_41_46.pdf

Esto para mi seria el punto de partida, empezar por comprobar que utils.dll funciona correctamente y que es llamada de forma correcta, ya que parece que es esta dll la que da todos los problemas.

A partir de aquí, ya seria trabajar el código .NET hasta que funcionara correctamente.

Una recomendación que te haría seria, si es posible, intentar que la DLL en .NET que construyes separara totalmente la aplicacion .NET de la clase utils.dll, o sea, que la aplicación no necesitara acceder para nada a la clase utils.dll ni la necesitara como referencia. De esta forma toda la interacción con utils.dll estaría contenida en un solo proyecto y seria más fácil localizar errores. Por lo que he visto, en tu DLL en .NET usas la clase CParametro de utils.dll, esta clase, suponiendo que aceptara un parámetro de tipo texto, la podrías encapsular de la forma:

Public Class CComunicacion

Private _parametroEntrada As Utiles.CParametro
Private _parametroSalida As Utiles.CParametro

'en este ejemplo trato los parámetros de entrada y salida como strings,
'pero pueden ser tratados como integer,object,...
Public WriteOnly Property ParametroEntrada() As String
Set(ByVal value As String)
'aquí se habrían de realizar las conversiones para convertir el texto
'de entrada en un utiles.cparametro
_parametroEntrada = value
End Set
End Property

Public ReadOnly Property ParametroSalida() As String
Get
'aquí se habrían de realizar las conversiones para convertir el utiles.cparametro
'en un string
Return CStr(_parametroSalida)
End Get
End Property

End Class

La idea es que toda la comunicación entre la aplicación .NET y la DLL.NET se realizara mediante tipos simples del .NET y que la DLL.NET se encargara de convertirlos a tipos de utils.dll y de toda la comunicación con utils.dll. De esta forma te quedaría todo mucho mas encapsulado y los problemas con utils.dll quedarían restringidos a la DLL.NET y no a la aplicación. Pero esto es mi recomendación.

Espero haberte ayudado, y si tienes otras dudas o necesitas mas ayuda, pues para esta tienes el foro.
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
0
Comentar

RE:Problemas instanciando clase de una DLL

Publicado por David (5 intervenciones) el 20/07/2009 19:59:49
Hola,

a ver, te comento por partes...

He probado a "quitar" la parte de la dll utils.dll y funciona, me deja agregar la DLL.NET en la aplicación y ejecutar sus procedimientos. Pero claro, no puedo hacer eso porque necesito usar esa dll como interfaz de comunicación con otra aplicación.

Mi duda es, ¿se puede hacer algo para que esa utils.dll no de problemas al agregarla? Al principio de comenzar mis pruebas hace tiempo la agregue sin problemas a mi DLL.NET y las pruebas funcionaban perfectamente, accediendo tanto desde la aplicación como desde la DLL.NET a las variables de la clase de utils.dll (esto es necesario al ser la interfaz de comunicación con otra aplicación externa, no puedo acceder solo desde la DLL), incluso llamando desde la apliacación a mi DLL.NET con lo siguiente:

Dim clase As Object
clase = CreateObject("ModuloCom.CComunicacion")

Sin embargo, no se si al volver a empezar el trabajo (tuve que cambiar de visual studio 2008 a 2005) hice algo distinto y ahora no funciona bien.

En mi DLL.NET tengo la referencia añadida de utils.dll, pero si intento hacer lo mismo en una dll nueva u otra aplicación me da error. Incluso creo que al principio cuando funcionaba correctamente, al agregar la referencia aparecia en la pestaña de COM y ahora no. Se puede hacer que la "reconozca" y aparezca ahí? Te confirmo que está hecha en VB6, ya que sus autores así me lo dijeron, y además desde VB6 deja agregarla perfectamente en una aplicación/dll nueva.

Gracias de nuevo.
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
0
Comentar
sin imagen de perfil

RE:Problemas instanciando clase de una DLL

Publicado por Joan F (129 intervenciones) el 21/07/2009 07:10:59
Si la DLL esta hecha con VB6 no has de tener ningún problema para usarla en cualquier proyecto de VB.NET.

Por lo que me explicas parece ser que el problema es que la DLL no esta registrada en el sistema. Para registrar la DLL has de usar REGSVR32.EXE que esta en el directorio SYSTEM32 de windows.

Lo que se ha de hacer es abrir una ventana de comando (bien con el símbolo del sistema o ejecutando CMD) y ejecutar:

REGSVR32.EXE [ruta de la dll a registrar]

Otra opción es crear un acceso directo a C:WINDOWSSYSTEM32REGSVR32.EXE y arrastrar la DLL que quieres registrar al acceso directo.

Al final te ha de salir una ventana de mensaje indicando que el registro se ha realizado correctamente. Después de registrar la dll, esta te habría de de aparecer en la ventana COM y funcionar sin problemas.
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
0
Comentar

RE:Problemas instanciando clase de una DLL

Publicado por Bruno (1 intervención) el 25/10/2012 23:59:08
hola.

vas bien solo que despues de crear el obj te falta hacer un llamado al metodo que necesitas usar de tu dll con

CallByName

Saludos.
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
0
Comentar