Académique Documents
Professionnel Documents
Culture Documents
by Ron Petrusha
04/26/2005
Como la primera lengua desarrollo rápido de aplicaciones, Visual Basic llamado la atención por su
elegante interfaz gráfica y facilidad de uso, lo que permitió un programador con poca experiencia para
llevar a cabo en cuestión de minutos lo que a menudo tomó días para programadores avanzados
utilizando lenguajes como C y C + +. Como resultado, Visual Basic atrajo a millones de nuevos
programadores, muchos de los cuales tal vez nunca han siquiera considerado la programación de no
haber sido por la sencillez del lenguaje. Debido a esta simplicidad, y porque Visual Basic fue
atrayendo un público que los proponentes de otras lenguas sólo podían soñar, la no-programadores de
Visual Basic (que eran realmente verde de envidia) contraatacó señalando a la inexperiencia de la
mayoría de los programadores de Visual Basic y al los problemas que se derivan de la meta de diseño
de Visual Basic de blindar el revelador de las complejidades del sistema operativo subyacente. Para
reforzar su argumento de que Visual Basic es insuficiente y poco desarrollados, los críticos le gustaba
señalar las muchas cosas "reales" que los programadores hacen los programadores de Visual Basic no
se puede. Tal vez la limitación más común que los críticos señalan continuamente es la incapacidad de
Visual Basic para crear una biblioteca estándar de Windows de enlace dinámico (DLL).
Ciertamente es verdad que fuera de la caja, Visual Basic no permite crear un archivo DLL de Windows
de la misma manera que se pueden crear otros tipos de proyectos, como un EXE estándar o un archivo
DLL de ActiveX. En este artículo vamos a ir a explorar para ver cómo Visual Basic genera sus
archivos ejecutables. En el proceso, vamos a descubrir que con un poco de trabajo extra, podemos, de
hecho, crear archivos DLL de Windows con Visual Basic.
Una librería de enlace dinámico (DLL) es una biblioteca de funciones y procedimientos que se puede
llamar desde una aplicación o archivo DLL otro. Uso de una biblioteca de esta forma tiene dos
funciones principales:
* Permite el intercambio de código. El mismo archivo DLL puede ser utilizada por muchos otros
archivos DLL y las aplicaciones. La API de Win32, por ejemplo, se implementa como una serie de
archivos DLL de Windows. Por otra parte, siempre y cuando varios procesos de carga de la misma DLL
en la misma dirección base, pueden compartir el código en el archivo DLL. En otras palabras, una
única DLL en la memoria se puede acceder por varios procesos.
* Se permite el desarrollo basado en componentes y modular, lo que hace que el desarrollo y el
proceso de actualización sea más fácil.
Normalmente, cuando una biblioteca estática se utiliza en el desarrollo de aplicaciones, los módulos
de la biblioteca debe estar vinculada a la aplicación final. Con la vinculación dinámica, los módulos
pueden residir en un archivo independiente “”DLL” que se carga de forma dinámica, ya sea cuando se
carga la aplicación o cuando sus funciones miembro son necesarios.
Una librería de enlace dinámico pueden incluir funciones internas, que sólo se puede llamar desde
dentro de la DLL. Su objetivo principal, sin embargo, es proporcionar funciones exportadas - es decir,
funciones que residen en un módulo de la DLL y se puede llamar desde otros archivos DLL y las
aplicaciones. Con frecuencia, una definición (. Def) del archivo se utiliza en C / C + + a la lista de las
exportaciones de un archivo DLL.
Un archivo DLL también incluye un punto de entrada opcional, que se llama cuando se carga un
proceso o subproceso o descarga el archivo DLL. Windows llama a este punto de entrada cuando se
carga un proceso y descarga el archivo DLL. También llama a la puerta de entrada cuando el proceso
crea o termina un hilo. Eso permite que el archivo DLL para realizar cualquiera por proceso y la
inicialización de cada aplicación y limpieza. La sintaxis de este punto de entrada, que debe utilizar la
convención de llamada estándar (usado por defecto en Visual Basic), es:
hInstDLL, es un long que contiene el identificador de instancia de la DLL. Este es el mismo módulo
de la DLL de manejar.
fdwReason, una constante que indica por qué el punto de entrada ha sido llamado. Los valores
posibles son:
DLL_PROCESS_ATTACH (1)
Un proceso se está cargando el archivo DLL. Cualquier inicialización por proceso se debe realizar.
DLL_THREAD_ATTACH (2)
El proceso está generando un nuevo hilo. Cualquier inicialización por hilo debe ser realizada.
DLL_THREAD_DETACH (3)
DLL_PROCESS_DETACH (0)
Un proceso es extraer el archivo DLL, o el proceso está saliendo. Cualquier limpieza por proceso se
debe realizar.
lpvReserved
El Código DLL
En el intento de desarrollar una DLL de Windows, vamos a crear una biblioteca muy simple de
funciones matemáticas. El siguiente es el código del archivo DLL, que vamos a almacenar en un
módulo de código (un archivo bas.) llamado MathLib:
Option Explicit
Increment = var + 1
End Function
Decrement = var - 1
End Function
Square = var ^ 2
End Function
varias características sobre el código vale la pena mencionar. La primera es que a pesar de que incluye
un procedimiento DllMain, ningún proceso o por la inicialización por subproceso debe realizarse. Así
DllMain simplemente devuelve True si se le llama con el argumento de fdwReason establece
DLL_PROCESS_ATTACH.
En segundo lugar, el punto de proporcionar un archivo DLL de Windows es permitir a otros idiomas
para llamarlo. Para garantizar la interoperabilidad, queremos limitarnos a las características del
lenguaje que la API de Win32 admite, por lo que nuestra DLL se puede llamar desde los entornos de
desarrollo y muchas plataformas como sea posible. Podríamos haber hecho cada uno de nuestros tres
funciones matemáticas más flexible, por ejemplo, mediante la definición tanto en el argumento de
entrada y el valor de retorno como variantes. Eso habría permitido a la función para determinar el tipo
de datos se deben interpretar los datos de entrada como, además del tipo de datos se debe devolver. Sin
embargo, la variante es un tipo de datos definidos por el COM, de componentes de Microsoft Modelo
de objetos, y no es un tipo de datos de la API Win32 reconoce. Así que en lugar, el código utiliza el
estándar de Win32 API de tipos de datos.
También necesitará un programa de prueba que nos diga si nuestra DLL de Windows funciona
correctamente. Para ello, se puede crear un proyecto EXE estándar con una forma y un módulo de
código. El módulo de código consiste simplemente en las instrucciones Declare que definen las
funciones que se encuentran en el archivo DLL:
En lugar de simplemente especificando el nombre del archivo DLL en la cláusula Lib, también debe
agregar la ruta completa al directorio que contiene el archivo DLL.
Option Explicit
Comencemos por crear un proyecto DLL ActiveX y ver lo que ocurre si tratamos de llamar como si
fuera una norma DLL de Windows. Al crear un proyecto DLL ActiveX, Visual Basic agrega
automáticamente un módulo de clase (un archivo. cls) a la misma. Puede cambiar el nombre si desea,
pero no incluye ningún código. En su lugar, agregue un módulo de código (un archivo. BAS) para el
proyecto, agregar el código del archivo DLL y, a continuación, compile la DLL. Al ejecutar la aplicación
de prueba DLL, el diálogo de mensaje de error que se muestra en la Figura 1 aparece. El mensaje de
error indica que, aunque se encontró el archivo DLL, la función específica llamada (incremento) no lo
era.
Figura 1. Error al acceder a un archivo DLL de ActiveX como un archivo DLL de Windows
La causa más probable de este error es que la función no es exportadas por la DLL. Podemos utilizar
la utilidad DUMPBIN para examinar las exportaciones de un archivo DLL mediante el uso de la sintaxis
0 characteristics
41B9E52C time date stamp Fri Dec 10 10:04:28 2004
0.00 version
1 ordinal base
4 number of functions
4 number of names
1 0 0000192E DllCanUnloadNow
2 1 00001902 DllGetClassObject
3 2 00001918 DllRegisterServer
4 3 000018EC DllUnregisterServer
Summary
1000 .data
1000 .reloc
1000 .rsrc
1000 .text
Nuestras exportaciones DLL cuatro funciones, todas las cuales son las funciones de utilidad que
soporte COM. Es evidente que necesitamos para exportar DllMain y nuestros tres funciones
matemáticas. Pero, ¿cómo? Visual Basic no parece que le permiten exportar funciones DLL de
ActiveX DLL, por lo que efectivamente le impide el uso de Visual Basic para crear un estándar DLL
de Windows.
Esta dificultad, sin embargo, no es insuperable. Cuando se selecciona el menú Archivo -.> Crear
<filename> opción de menú dll para crear un archivo DLL de ActiveX, parece que Visual Basic es la
perfección de tomar nuestro código fuente y la salida de un archivo DLL de ActiveX. Pero si
examinamos el subdirectorio en el que Visual Basic se ha instalado, parece que el proceso no es tan
perfecta. Junto con VB6.exe, el ejecutable de Visual Basic que define el entorno de Visual Basic,
también podemos encontrar C2.EXE y LINK.EXE, que es un compilador y un enlazador,
respectivamente. Su presencia en este directorio sugiere que VB6.exe no se ocupa por si mismo de la
generación de la DLL, pero que en algún momento en el proceso de compilación, se llama a estos
programas.
Podemos encontrar la manera de Visual Basic utiliza el compilador y enlazador más precisamente
cambiando el nombre de ellos y crear ejecutables contenedor llamado C2 y LINK que a su vez llamar
al compilador y enlazador real. El siguiente es el código fuente de una nueva versión de un C2.EXE
consola de modo que llama a la "real" del compilador C2, que hemos cambiado el nombre
C2comp.exe:
Public Sub Main()
strCmd = Command
strPath = App.Path
ts.WriteLine "Beginning execution at " & Date & " " & Time()
ts.WriteBlankLines 1
ts.WriteLine "Command line parameters to c2 call:"
ts.WriteLine " " & strCmd
ts.WriteBlankLines 1
ts.WriteLine "Calling C2 compiler"
ts.WriteBlankLines 1
ts.WriteLine "Returned from c2 compiler call"
ts.Close
End Sub
El proceso de implantación de un archivo DLL ActiveX produce la siguiente salida en nuestro archivo
de registro:
Calling C2 compiler
Estos argumentos son bastante estándar de línea de comandos para generar archivos objeto que a su
vez se suministran al vinculador. Eso significa que para determinar la manera de producir un archivo
DLL de Windows, vamos a tener que interceptar la llamada al enlazador para que podamos ver lo que
los argumentos de Visual Basic pasa a ella. El siguiente código hace lo siguiente:
Public Sub Main ()
Se requiere que cambie el nombre del LinkLnk.exe enlazador y el nombre de nuestro Link.exe
contenedor enlace.
Cuando tratamos de elaborar un proyecto DLL ActiveX, nuestro archivo de registro vinculador
contiene el siguiente resultado:
Beginning execution at 12/11/2004 12:44:33 PM
Así, después de examinar la tabla un archivo DLL de ActiveX de exportación, interceptar llamadas de
Visual Basic para el compilador, interceptar llamadas de Visual Basic para el enlazador, y la
comparación de los argumentos pasados al vinculador con las exigidas a C / C + + para generar un
archivo DLL de Windows, Por fin has identificado por las que no son capaces de crear con éxito un
archivo DLL de Windows con Visual Basic. Y afortunadamente, podemos evitar esa restricción.
Debemos ser capaces de crear un estándar de archivo DLL de Windows si no hacemos lo siguiente:
1. Cree un archivo. def para nuestro proyecto. Podemos especificar nuestras funciones
exportadas en el archivo de definición de varias maneras, pero lo mejor es mantenerlo simple.:
NAME MathLib
LIBRARY MathMod
DESCRIPTION "Add-on Library of Mathematical Routines"
EXPORTS DllMain @1
Increment @2
Decrement @3
Square @4
La instrucción NAME define el nombre de la DLL. La instrucción LIBRARY o debe preceder a la lista de
funciones exportadas o aparecer en la misma línea que la primera función. El archivo de definición.
También se enumerarán la posición ordinal de cada función exportada precedido por un símbolo @.
2 Decidir cómo queremos para interceptar la llamada al enlazador. Dos técnicas principales son
disponibles para hacer esto:
El parcheo de las importaciones de tabla de dirección (IAT), que exige que se construye un
Visual Basic complemento que modifica el TAI con el fin de interceptar llamadas en particular por
Visual Basic para la API de Win32. Aunque es sin duda el método más elegante, su complejidad hace
que sea un tema digno de un artículo separado.
La construcción de un enlazador proxy que intercepta la llamada al enlazador real, modifica los
argumentos de línea de comandos para pasar al enlazador, y luego llama al enlazador con los
argumentos correctos de línea de comandos. Este es el enfoque que utiliza para descubrir lo que los
argumentos de Visual Basic se pasa al compilador y enlazador, y es el enfoque que va a adoptar para
crear un archivo DLL de Windows.
En la construcción de nuestro enlazador proxy, queremos un diseño lo suficientemente flexible para
que podamos generar otros tipos de archivos, en caso necesario.
3 Modificar los argumentos para el enlazador para agregar el / DEF interruptor junto a la ruta y el
nombre de nuestro archivo def.. Para ello, debe crear un estándar de Visual Basic proyecto EXE,
agregue una referencia al Microsoft Scripting Runtime Library, quitar el formulario del proyecto, y
añadir un módulo de código. El código fuente para el enlazador proxy es la siguiente:.
Option Explicit
strCmd = Command
ts.WriteLine "Beginning execution at " & Date & " " & Time()
ts.WriteBlankLines 1
ts.WriteLine "Command line arguments to LINK call:"
ts.WriteBlankLines 1
ts.WriteLine " " & strCmd
ts.WriteBlankLines 2
ts.WriteBlankLines 1
ts.WriteLine "Returned from linker call"
ts.Close
End Sub
Este vinculador proxy modifica sólo los argumentos de línea de comandos se pasa al vinculador si un
archivo de definición está en el directorio que contiene el proyecto de Visual Basic;. de lo contrario,
simplemente pasa los argumentos de línea de comandos en el enlazador sin cambios. Si un archivo de
definición. está presente, se agrega un modificador / DEF para la línea de comandos. También se
determina si los archivos de recursos se van a agregar a la lista de archivos vinculados. Por último,
examina la tabla de exportación para determinar si una función llamada CPlApplet está presente, si es
así, cambia la extensión del archivo de salida es de dll para cpl...
4.
Para instalar el enlazador proxy, cambiar el nombre original de Visual Basic vinculador
LinkLnk.exe, copie el enlazador proxy en el directorio de Visual Basic, y el nombre de Link.exe.
Una vez que creemos nuestro enlazador proxy, que puede volver a cargar nuestro proyecto MathLib y
compilarlo en un archivo DLL seleccionando la opción Hacer MathLib.exe en el menú Archivo.
Prueba de la DLL
Una vez que creemos nuestro DLL de Windows, el paso final es poner a prueba para asegurarse de
que funciona. Para ello, cree un nuevo proyecto EXE estándar (llamémosla MathLibTest) y añadir un
módulo de código. Para asegurarse de que el código en nuestro proyecto se puede acceder a las
funciones exportadas por la DLL, se utiliza el estándar de Visual Basic instrucción Declare. Declaramos
nuestros tres exportados rutinas matemáticas en el módulo de código de la siguiente manera:
Option Explicit
A continuación, puede utilizar el código siguiente en el módulo de formulario para llamar a las rutinas
en el archivo DLL:
Option Explicit
Cuando llamamos a cada una de las funciones MathLib, la ventana de la aplicación puede aparecer
como lo hace en la figura 2, lo que confirma que las llamadas a las rutinas MathLib funciona como se
esperaba.