Desde que se creó el "Visual Basic 6.0 Resource Center" (aka
VBRun) como
respuesta para los usuarios de VB6 en tiempos del .NET Framework se han
manejado tres secciones, las cuales se corresponden con las tres posiciones
frente que hacer con una aplicación VB6 "legada" con respecto a .NET, las cuales son:
A continuación, una comparativa de los puntos a favor y en contra de las tres
opciones:
| |
A favor: |
En contra: |
| Mantenerse en VB6 |
|
- No es posible agregar nueva funcionalidad
- La disponibiliad de información y componentes
disminuye
- El ciclo de vida de VB6 se termina
|
| Fusión Visual Basic |
- Acceso a la nueva tecnología
- Bajo riesgo
- Retorno de Inversión en corto tiempo
|
- Alto dominio del tema de Interoperabilidad
- Retos de depuración especiales
- El ciclo de vida de VB6 se termina
|
| Migrar a .NET |
- Acceso y aprovechamientos de la nueva
tecnología
- Mayor productividad de desarrollo
- Gran cantidad de información y herramientas
que aumenta día a día
|
- Riesgoso, dado que no es algo trivial
- Alto consumo de recursos, principalmente de
tiempo
|
Desde mi punto de vista, mantenerse en VB6 sólo es una opción para
aquellas aplicaciones que funcionan bien tal y como están, y que no han requerido
ser modificadas sustancialmente en los pasados dos
años. De
otra manera conviene ir evaluando cualquiera de las otras dos opciones.
Al otro extremo de no hacer nada está el "dar el siguiente paso", "seguiendo el camino" marcado por
.NET. Es decir, actualizar tanto las aplicaciones
(como de las habilidades de los desarrolladores) de VB6 a VB.NET / VB2005. Es la
opción en la que he
insistido y que tiene muchos "sabores", desde
conversiones con asistentes -con algunas modificaciones manuales,
migraciones parciales o por niveles del código, hasta la reescritura gradual
pero total de la aplicación.
No obstante hasta el momento no había mencionado la opción intermedia:
VB Fusion ("Fusión Visual Basic") que en pocas
palabras consiste en la utilización de la biblioteca de clases del .NET
Framework desde VB6 gracias a la
Interoperabilidad .NET.
Fusión Visual Basic
VB Fusion es ideal para quienes les llama la atención las bondades
del .NET Framework pero por alguna u otra razón no pueden darse el lujo
"seguir el camino" del mismo y actualizarse de lleno. Por otro lado sin
embargo ésta medida no excluye la necesidad de actualizar las habilidades de
los desarrolladores para dominar el .NET Framework, ya que se requiere
conocer cómo funciona y que ofrece el mismo para sacarle provecho.
De hecho VB Fusion requiere el saber afrontar los problemas de
desarrollo y depuración concernientes a la Interoperabilidad COM/.NET, que
no se requieren en el desarrollo de aplicaciones 100% .NET. Esto se debe a
que, como ha de saber, las aplicaciones VB6 son aplicaciones construidas a
partir de componentes COM: Los controles ActiveX, los objetos ADO y muchos
otros componentes de terceros utilizados para la construcción de
aplicaciones VB6 son componentes COM, del mismo modo las DLL construidas con
VB6 son componentes COM que exponen objetos por medio de dicho estándar. Por
el contrario las aplicaciones y componentes construidos con VB.NET/VB2005 no
son aplicaciones COM, por lo que no exponen objetos COM, al menos no de
manera predeterminada. Esta incompatibilidad de construcción entre las
plataformas COM y .NET se supera gracias a una capa intermedia de
Interoperabilidad entre ambas, no
obstante requiere del conocimiento y dominio de ciertas reglas.
Un buen punto de partida sobre VB Fusion es el articulo
Using .NET from Visual Basic 6.0, que como su título lo indica
muestra como utilizar algunas de las clases del .NET Framework desde Visual
Basic 6.0 con tan sólo dos pasos:
- Registrar el archivo System.dll, propiamente llamado ensamblado
.NET, con la Herramienta de registro de ensamblados .NET (regasm.exe)
con el siguiente comando:
regasm System.dll
Lo cual registra la interfase COM del ensamblado, en este caso
System.dll, para que aquellos objetos expuestos a través de la misma
puedan ser utilizados por cualquier entorno COM, tal como VB6. Para
mayor información leer
Herramienta Registro de ensamblados (Regasm.exe).
- Agregar una referencia en un proyecto Visual Basic 6 hacia "System.dll", tal y como lo haríamos con
un
componente COM.
Una vez hecho lo anterior se pueden hacer uso de algunas clases
contenidas en System.dll desde VB6, como si de objetos COM se trataran.
No obstante para que un ensamblado pueda ser registrado en COM el mismo
debe seguir una serie de reglas para que se puedan presentar como objetos COM, dada las restricción de dichas reglas no todas las clases
del ensamblado System.dll pueden ser llamadas directamente desde VB6. Por
esa misma razón no basta utilizar regasm.exe con todos los ensamblados .NET para
poder tener toda la funcionalidad del .NET Framework en VB6. De hecho en la
mayoría de los casos, sobretodo cuando se desee utilizar ensamblados .NET
propios o de terceros, primero se deberán crear Bibliotecas de Clases COM con
Visual Basic .NET o Visual Basic 2005, las cuales funcionarán a modo de
"wrappers" entre la aplicación VB6 y el .NET Framework.

Los detalles para la creación de "Clases Wrapper" se encuentran en el
artículo:
Use 5000 Classes from Visual Basic 6.0 el cual muestra paso a
paso cómo podemos ir más allá y aprovechar incluso aquellas clases que no
están disponibles con solo agregar una referencia a los ensamblados .NET
registrados en COM. Todo gracias a nuestras clases COM, las cuales deberán estar
"adornadas" con el
Atributo ComClass —que nos permite exponer una clase como un objeto COM— de manera similar a la siguiente:
<ComClass(MyWrapper.ClassId, MyWrapper.InterfaceId, MyWrapper.EventsId)> _
Public Class MyWrapper
#Region "COM GUIDs"
' Estos GUID proporcionan la identidad COM para esta clase
' y sus interfaces COM. Si los cambia, los clientes existentes
' ya no podrán obtener acceso a la clase.
Public Const ClassId As String = "B3F1236F-574D-4A5D-AF2A-150652B10093"
Public Const InterfaceId As String = "76AC8AB6-1BF7-40D3-85D6-E9C57FFC1E3F"
Public Const EventsId As String = "2F3F3A19-604B-40F6-A20A-43EB610E7065"
#End Region
Reglas para la creación de Clases COM
Las clases COM creadas con VB.NET / VB2005 además deberán seguir ciertas reglas para la correcta
Interoperabilidad con COM, las cuales son:
- Deben exponer un solo constructor sin parámetros
- Los tipos de datos deben ser correctamente convertidos entre VB.NET
y VB6
- No deben exponer funciones Shared (o estáticas)
- No pueden exponer funciones sobrecargadas, deberán renombrarse con
un nombre único
- Los ensamblados (DLL) deberán colocarse en el Global Assembly Cache
1. Constructor por default
A pesar que VB.NET nos permite implementar constructores que aceptan
parámetros, la clase COM deberá exponer sólo el constructor por default, es
decir el constructor simple sin parámetros. Esto debido a que es un
requisito de los objeto COM para que puedan ser registrado y ser creados
mediante CreateObject. De hecho ésta restricción es una de las causas por la
que muchas clases del .NET Framework no pueden ser usadas directamente desde
VB6 y la razón por la que se necesitan crear wrappers. Para aquellas clases
.NET cuyo constructor requiere argumentos debemos crear la clase COM con un constructor sin argumentos y
crear la instancia de la clase en otro método
adicional, o bien en una propiedad.
Public Sub New()
MyBase.New()
End Sub
Private dirInfo As DirectoryInfo
Public Sub SetPath(ByVal Path As String)
dirInfo = New DirectoryInfo(Path)
End Sub
2. Conversión de tipos de datos
Gran parte del esfuerzo en la construcción de los wrappers se lleva en la
tarea de conversión entre los tipos de datos de VB6 y los de VB.NET. La
siguiente tabla muestra las únicas conversiones directas que se pueden hacer
entre ellos:
| Visual Basic .NET |
Visual Basic 6 |
| Boolean |
Boolean |
| Byte |
Byte |
| DateTime |
Date |
| Double |
Double |
| Integer (Int32) |
Long |
| Short (Int16) |
Integer |
| Single |
Single |
| String |
String |
| Object |
Object |
Dada la rica cantidad de tipos que existe en VB.NET los tipos que no
están en la tabla anterior deberán ser convertidos explícitamente a tipos
más simples convenientes, tal como String u algún otro tipo numérico
soportado por VB6. Otra opción es utilizar el
atributo MarshalAs el cual nos ayuda a indicar la forma de calcular las
referencias de los datos entre código administrado .NET y el código no
administrado, en nuestro caso VB6.
Public Function Calculate( _
<MarshalAs(UnmanagedType.Currency)> ByVal data As Decimal) As _
<MarshalAs(UnmanagedType.Currency)> Decimal
Dim d As Decimal
'...
Return d
End Function
3. Funciones Shared
Esta es la segunda razón por la que muchas clases del .NET Framework
requieren un wrapper. Las funciones Shared (también conocidas como
estáticas) de las clases "utilitarias" del
.NET Framework no requieren una instancia de la misma para ser utilizadas, no obstante
los objetos COM no pueden operar de ésa manera. La solución es simple:
Convertir a las funciones Shared en funciones de un objeto, creando una
clase COM con funciones miembro que encapsularán a las funciones Shared, las
cuales ahora se utilizaran a partir de una instancia de la misma: un objeto
COM.
Public Class Directory
Public Sub New()
MyBase.New()
End Sub
Public Function Exists(ByVal Path As String) As Boolean
Return Directory.Exists(Path)
End Function
End Class
4. Funciones sobrecargadas
Dado que COM no soporta funciones sobrecargadas, deberá implementarse
dentro de la clase COM las distintas versiones de una función sobrecargada con nombres únicos y
descriptivos, de preferencia con la misma raíz.
Public Sub Delete(ByVal Path As String)
Directory.Delete(Path)
End Sub
Public Sub DeleteRecursive(ByVal Path As String, _
ByVal Recursive As Boolean)
Directory.Delete(Path, Recursive)
End Sub
5. Global Assembly Cache
Dado que los archivos de los componenetes COM pueden estar ubicados en
cualquier sitio del disco, el registro COM necesita almacenar la ubicación del
archivo de modo que puedan cargarse los objetos en memoria. Por esa razón
conviene asegurarse que COM pueda localizar al ensamblado que contiene las
clases COM. La mejor manera de
localizar a un ensamblado de modo global e inequívoco es colocarlo dentro del caché
global de ensamblados: GAC, lo que se realiza en dos pasos: 1ro. Firmar
el ensamblado con un nombre seguro, ya sea de forma manual o bien desde las
Propiedades del proyecto con VB2005; y 2do. Colocar el ensamblado firmado en el GAC con
la ayuda de la
Herramienta
del Caché global de ensamblados (gacutil.exe). Puede revisar el procedimiento
manual paso a paso en:
How to install an
assembly in the Global Assembly Cache in Visual Basic .NET or in Visual
Basic 2005.
Finalmente, dado que VB Fusion se vale de la
Interoperabilidad COM y .NET, se requiere de un fuerte dominio sobre dicho
tema si se desea seguir por ésta vía. Por ello es recomendable leer el
artículo:
Solución de problemas de interoperabilidad de .NET y toda la
documentación al respecto en MSDN Library. Así como aprovechar también la
descarga gratuita y legal del libro de la editorial Apress:
COM and .NET Interoperability (PDF 6.36 MiB).
Conclusión
Existen tres opciones para afrontar las
aplicaciones "legadas" de VB6, cada una con sus ventajas y desventajas, las
cuales deberian evaluarse con sumo cuidado para elegir la adecuada.
En éste artículo dimos una vistazo a la interesante opción de VB Fusion,
la cual aprovecha el código actualmente construido en VB6 y lo enriquece con
funcionalidad del .NET Framework gracias a la Interoperabilidad .NET que
nos permite el uso clases de ensamblados .NET desde VB6. Por último listamos
las reglas a seguir para la construcción de Clases COM en VB.NET/ VB2005 para
exponer mayor cantidad de clases del .NET Framework hacia VB6.