¿Qué es un archivo DLL?


Resumen


En este artículo se describe lo que es una biblioteca de vínculos dinámicos (DLL) y los diversos problemas que pueden producirse al usar archivos DLL.A continuación, en este artículo se describen algunos problemas avanzados que debe tener en cuenta al desarrollar sus propios archivos DLL. Al describir lo que es un archivo DLL, en este artículo se describen los métodos de vinculación dinámica, las dependencias de DLL, los puntos de entrada de DLL, la exportación de funciones DLL y las herramientas de solución de problemas de DLL.Este artículo finaliza con una comparación de alto nivel de archivos DLL con los ensamblados de Microsoft .NET Framework.

INTRODUCCIÓN


Para los sistemas operativos Microsoft Windows que se enumeran en la sección "Se aplica a", gran parte de la funcionalidad del sistema operativo se proporciona mediante bibliotecas de vínculos dinámicos (DLL). Además, cuando se ejecuta un programa en uno de estos sistemas operativos Windows, gran parte de la funcionalidad del programa puede ser proporcionada por los archivos DLL. Por ejemplo, algunos programas pueden contener muchos módulos diferentes, y cada módulo del programa está contenido y distribuido en DLL.El uso de archivos DLL ayuda a promover la modularización de código, reutilización de código, uso eficiente de memoria y reducción de espacio en disco. Por lo tanto, el sistema operativo y los programas se cargan más rápido, se ejecutan más rápido y toman menos espacio en disco en el equipo. Cuando un programa utiliza un archivo DLL, un problema que se denomina dependencia puede hacer que el programa no se ejecute. Cuando un programa utiliza un archivo DLL, se crea una dependencia. Si otro programa sobrescribe y rompe esta dependencia, es posible que el programa original no se ejecute correctamente. Con la introducción de Microsoft .NET Framework, la mayoría de los problemas de dependencia se han eliminado mediante ensamblados.

Más información


¿Qué es un archivo DLL?

Un archivo DLL es una biblioteca que contiene código y datos que pueden ser utilizados por más de un programa al mismo tiempo. Por ejemplo, en los sistemas operativos Windows, el archivo DLL Comdlg32 realiza funciones comunes relacionadas con el cuadro de diálogo. Por lo tanto, cada programa puede usar la funcionalidad contenida en este archivo DLL para implementar un cuadro de diálogo Abrir. Esto ayuda a promover la reutilización del código y el uso eficiente de la memoria.Mediante el uso de un archivo DLL, un programa se puede modular en componentes independientes. Por ejemplo, un programa de contabilidad se puede vender por módulo. Cada módulo se puede cargar en el programa principal en tiempo de ejecución si ese módulo está instalado. Dado que los módulos son independientes, el tiempo de carga del programa es más rápido y solo se carga un módulo cuando se solicita esa funcionalidad.Además, las actualizaciones son más fáciles de aplicar a cada módulo sin afectar a otras partes del programa. Por ejemplo, puede tener un programa de nómina y las tasas de impuestos cambian cada año. Cuando estos cambios se aíslan en un archivo DLL, puede aplicar una actualización sin necesidad de compilar o instalar todo el programa de nuevo.En la lista siguiente se describen algunos de los archivos que se implementan como archivos DLL en los sistemas operativos Windows:
  • Archivos de controles ActiveX (.ocx) Un ejemplo de un control ActiveX es un control de calendario que le permite seleccionar una fecha de un calendario.
  • Archivos del Panel de control (.cpl) Un ejemplo de un archivo .cpl es un elemento que se encuentra en el Panel de control. Cada elemento es un archivo DLL especializado.
  • Archivos del controlador de dispositivo (.drv) Un ejemplo de controlador de dispositivo es un controlador de impresora que controla la impresión en una impresora.

Ventajas de DLL

En la lista siguiente se describen algunas de las ventajas que se proporcionan cuando un programa utiliza un archivo DLL:
  • Utiliza menos recursos Cuando varios programas utilizan la misma biblioteca de funciones, un archivo DLL puede reducir la duplicación de código que se carga en el disco y en la memoria física. Esto puede influir en gran medida en el rendimiento no sólo del programa que se ejecuta en primer plano, sino también otros programas que se ejecutan en el sistema operativo Windows.
  • Promueve la arquitectura modular Un archivo DLL ayuda a promover el desarrollo de programas modulares. Esto le ayuda a desarrollar programas grandes que requieren varias versiones de idioma o un programa que requiere arquitectura modular. Un ejemplo de un programa modular es un programa de contabilidad que tiene muchos módulos que se pueden cargar dinámicamente en tiempo de ejecución.
  • Facilita la implementación y la instalación Cuando una función dentro de un archivo DLL necesita una actualización o una corrección, la implementación e instalación del archivo DLL no requiere que el programa se vuelva a vincular con el archivo DLL. Además, si varios programas utilizan el mismo archivo DLL, todos los programas se beneficiarán de la actualización o la corrección. Este problema puede producirse con más frecuencia cuando se utiliza un archivo DLL de terceros que se actualiza o se corrige regularmente.

Dependencias de DLL

Cuando un programa o un archivo DLL utiliza una función DLL en otro archivo DLL, se crea una dependencia. Por lo tanto, el programa ya no es autónomo, y el programa puede experimentar problemas si se rompe la dependencia. Por ejemplo, es posible que el programa no se ejecute si se produce una de las siguientes acciones:
  • Un archivo DLL dependiente se actualiza a una nueva versión.
  • Se corrige un archivo DLL dependiente.
  • Un archivo DLL dependiente se sobrescribe con una versión anterior.
  • Un archivo DLL dependiente se quita del equipo.
Estas acciones se conocen generalmente como conflictos DLL. Si no se aplica la compatibilidad con versiones anteriores, es posible que el programa no se ejecute correctamente.En la lista siguiente se describen los cambios que se han introducido en Microsoft Windows 2000 y en sistemas operativos Windows posteriores para ayudar a minimizar los problemas de dependencia:
  • Protección de archivos de Windows En Protección de archivos de Windows, el sistema operativo impide que un agente no autorizado actualice o elimine los archivos DLL del sistema. Por lo tanto, cuando una instalación del programa intenta quitar o actualizar un archivo DLL que se define como un archivo DLL del sistema, Windows File Protection buscará una firma digital válida.
  • DLL privadas Los archivos DLL privados le permiten aislar un programa de los cambios realizados en los archivos DLL compartidos. Para usar archivos DLL privados, busque los archivos DLL en la carpeta raíz del programa. A continuación, para los nuevos programas, agregue información específica de la versión al archivo DLL. Para programas antiguos, utilice un archivo .local vacío. Cada método indica al sistema operativo que utilice los archivos DLL privados que se encuentran en la carpeta raíz del programa.

Herramientas de solución de problemas de DLL

Hay varias herramientas disponibles para ayudarle a solucionar problemas de DLL. Las siguientes herramientas son algunas de estas herramientas.

Dependency Walker

La herramienta Dependency Walker puede buscar recursivamente todos los archivos DLL dependientes que utiliza un programa. Al abrir un programa en Dependency Walker, Dependency Walker realiza las siguientes comprobaciones:
  • Dependency Walker comprueba si faltan archivos DLL.
  • Dependency Walker comprueba si hay archivos de programa o archivos DLL que no son válidos.
  • Dependency Walker comprueba que las funciones de importación y exportación coincidan.
  • Dependency Walker comprueba si hay errores de dependencia circulares.
  • Dependency Walker comprueba si hay módulos que no son válidos porque los módulos son para un sistema operativo diferente.
Mediante el uso de Dependency Walker, puede documentar todos los archivos DLL que utiliza un programa. Esto puede ayudar a prevenir y corregir los problemas de DLL que pueden ocurrir en el futuro. Dependency Walker se encuentra en el siguiente directorio al instalar Microsoft Visual Studio 6.0:
unidadde archivos de programa, Microsoft Visual Studio, Common, Herramientas

Solucionador de problemas universal de DLL

La herramienta DLL Universal Problem Solver (DUPS) se utiliza para auditar, comparar, documentar y mostrar información de DLL. En la lista siguiente se describen las utilidades que componen la herramienta DUPS:
  • Dlister.exe Esta utilidad enumera todos los archivos DLL del equipo y registra la información en un archivo de texto o en un archivo de base de datos.
  • Dcomp.exe Esta utilidad compara los archivos DLL que se enumeran en dos archivos de texto y genera un tercer archivo de texto que contiene las diferencias.
  • Dtxt2DB.exe Esta utilidad carga los archivos de texto que se crean mediante la utilidad Dlister.exe y la utilidad Dcomp.exe en la base de datos dllHell.
  • DlgDtxt2DB.exe Esta utilidad proporciona una versión de interfaz gráfica de usuario (GUI) de la utilidad Dtxt2DB.exe.
Para obtener más información acerca de la herramienta DUPS, haga clic en el número de artículo siguiente para verlo en Microsoft Knowledge Base:
247957 Uso de DUPS.exe para resolver problemas de compatibilidad con DLL

Base de datos de ayuda de DLL

La base de datos de Ayuda de DLL le ayuda a localizar versiones específicas de archivos DLL instalados por los productos de software de Microsoft.

Desarrollo de DLL

En esta sección se describen los problemas y los requisitos que debe tener en cuenta al desarrollar sus propios archivos DLL.

Tipos de archivos DLL

Al cargar un archivo DLL en una aplicación, dos métodos de vinculación permiten llamar a las funciones DLL exportadas. Los dos métodos de vinculación son la vinculación dinámica en tiempo de carga y la vinculación dinámica en tiempo de ejecución.
Vinculación dinámica en tiempo de carga
En la vinculación dinámica en tiempo de carga, una aplicación realiza llamadas explícitas a funciones DLL exportadas como funciones locales. Para utilizar la vinculación dinámica en tiempo de carga, proporcione un archivo de encabezado (.h) y un archivo de biblioteca de importación (.lib) al compilar y vincular la aplicación. Al hacerlo, el vinculador proporcionará al sistema la información necesaria para cargar el archivo DLL y resolver las ubicaciones de función DLL exportadas en tiempo de carga.
Vinculación dinámica en tiempo de ejecución
En la vinculación dinámica en tiempo de ejecución, una aplicación llama a la función LoadLibrary o a la función LoadLibraryEx para cargar el archivo DLL en tiempo de ejecución. Una vez que el archivo DLL se carga correctamente, utilice la función GetProcAddress para obtener la dirección de la función DLL exportada a la que desea llamar. Cuando se utiliza la vinculación dinámica en tiempo de ejecución, no es necesario un archivo de biblioteca de importación.En la lista siguiente se describen los criterios de aplicación para cuándo utilizar la vinculación dinámica en tiempo de carga y cuándo utilizar la vinculación dinámica en tiempo de ejecución:
  • Rendimiento de la startup Si el rendimiento inicial de inicio de la aplicación es importante, debe usar la vinculación dinámica en tiempo de ejecución.
  • Facilidad de uso En la vinculación dinámica en tiempo de carga, las funciones DLL exportadas son como funciones locales. Esto hace que sea fácil para usted llamar a estas funciones.
  • Lógica de la aplicación En la vinculación dinámica en tiempo de ejecución, una aplicación puede bifurcarse para cargar diferentes módulos según sea necesario. Esto es importante cuando se desarrollan versiones en varios idiomas.

El punto de entrada de DLL

Al crear un archivo DLL, puede especificar opcionalmente una función de punto de entrada. Se llama a la función de punto de entrada cuando los procesos o subprocesos se adjuntan al archivo DLL o se separan del archivo DLL. Puede utilizar la función de punto de entrada para inicializar estructuras de datos o para destruir estructuras de datos según lo requiera el archivo DLL. Además, si la aplicación es multiproceso, puede usar el almacenamiento local de subprocesos (TLS) para asignar memoria privada a cada subproceso de la función de punto de entrada. El código siguiente es un ejemplo de la función de punto de entrada DLL.
BOOL APIENTRY DllMain(HANDLE hModule,// Handle to DLL moduleDWORD ul_reason_for_call,// Reason for calling functionLPVOID lpReserved ) // Reserved{switch ( ul_reason_for_call ){case DLL_PROCESS_ATTACHED:// A process is loading the DLL.break;case DLL_THREAD_ATTACHED:// A process is creating a new thread.break;case DLL_THREAD_DETACH:// A thread exits normally.break;case DLL_PROCESS_DETACH:// A process unloads the DLL.break;}return TRUE;}
Cuando la función de punto de entrada devuelve un valor FALSE, la aplicación no se iniciará si utiliza la vinculación dinámica en tiempo de carga. Si utiliza la vinculación dinámica en tiempo de ejecución, solo se cargará el archivo DLL individual.La función de punto de entrada solo debe realizar tareas de inicialización sencillas y no debe llamar a ninguna otra función de carga o terminación de DLL. Por ejemplo, en la función de punto de entrada, no debe llamar directa o indirectamente a la función LoadLibrary o a la función LoadLibraryEx. Además, no debe llamar a la función FreeLibrary cuando finaliza el proceso.Nota En aplicaciones multiproceso, asegúrese de que el acceso a los datos globales de DLL está sincronizado (seguro para subprocesos) para evitar posibles daños en los datos. Para ello, use TLS para proporcionar datos únicos para cada subproceso.

Exportación de funciones DLL

Para exportar funciones DLL, puede agregar una palabra clave de función a las funciones DLL exportadas o crear un archivo de definición de módulo (.def) que muestre las funciones DLL exportadas.Para utilizar una palabra clave function, debe declarar cada función que desea exportar con la siguiente palabra clave:
__declspec(dllexport)
Para utilizar funciones DLL exportadas en la aplicación, debe declarar cada función que desea importar con la siguiente palabra clave:
__declspec(dllimport)
Normalmente, usaría un archivo de encabezado que tiene una instrucción define y una instrucción ifdef para separar la instrucción export y la instrucción import.También puede utilizar un archivo de definición de módulo para declarar funciones DLL exportadas. Cuando se utiliza un archivo de definición de módulo, no es necesario agregar la palabra clave function a las funciones DLL exportadas. En el archivo de definición de módulo, se declaran la instrucción LIBRARY y la instrucción EXPORTS para el archivo DLL. El código siguiente es un ejemplo de un archivo de definición.
// SampleDLL.def//LIBRARY "sampleDLL"EXPORTS  HelloWorld

DLL de ejemplo y aplicación

En Microsoft Visual C++ 6.0, puede crear un archivo DLL seleccionando el tipo de proyecto Biblioteca de vínculos dinámicos de Win32 o elTipo de proyecto MFC AppWizard (dll).El código siguiente es un ejemplo de un archivo DLL que se creó en Visual C++ mediante el uso de laTipo de proyecto Win32 Dynamic-Link Library.
// SampleDLL.cpp//#include "stdafx.h"#define EXPORTING_DLL#include "sampleDLL.h"BOOL APIENTRY DllMain( HANDLE hModule,                        DWORD  ul_reason_for_call,                        LPVOID lpReserved ){    return TRUE;}void HelloWorld(){MessageBox( NULL, TEXT("Hello World"), TEXT("In a DLL"), MB_OK);}
// File: SampleDLL.h//#ifndef INDLL_H#define INDLL_H#ifdef EXPORTING_DLLextern __declspec(dllexport) void HelloWorld() ;#elseextern __declspec(dllimport) void HelloWorld() ;#endif#endif
El código siguiente es un ejemplo de un proyecto de aplicación Win32 que llama a la función DLL exportada en el archivo DLL SampleDLL.
// SampleApp.cpp //#include "stdafx.h"#include "sampleDLL.h"int APIENTRY WinMain(HINSTANCE hInstance,                     HINSTANCE hPrevInstance,                     LPSTR     lpCmdLine,                     int       nCmdShow){ HelloWorld();return 0;}
Nota En la vinculación dinámica en tiempo de carga, debe vincular la biblioteca de importación SampleDLL.lib que se crea al compilar el proyecto SampleDLL.En la vinculación dinámica en tiempo de ejecución, se usa código similar al código siguiente para llamar a la función DLL exportada SampleDLL.dll.
...typedef VOID (*DLLPROC) (LPTSTR);...HINSTANCE hinstDLL;DLLPROC HelloWorld;BOOL fFreeDLL;hinstDLL = LoadLibrary("sampleDLL.dll");if (hinstDLL != NULL){    HelloWorld = (DLLPROC) GetProcAddress(hinstDLL, "HelloWorld");    if (HelloWorld != NULL)        (HelloWorld);    fFreeDLL = FreeLibrary(hinstDLL);}...
Al compilar y vincular la aplicación SampleDLL, el sistema operativo Windows busca el archivo DLL SampleDLL en las siguientes ubicaciones en este orden:
  1. La carpeta de la aplicación
  2. La carpeta actual
  3. La carpeta del sistema de Windows Nota La función GetSystemDirectory devuelve la ruta de acceso de la carpeta del sistema de Windows.
  4. La carpeta Windows Nota La función GetWindowsDirectory devuelve la ruta de acceso de la carpeta windows.

El ensamblado de .NET Framework

Con la introducción de Microsoft .NET y .NET Framework, la mayoría de los problemas asociados con los archivos DLL se han eliminado mediante ensamblados. Un ensamblado es una unidad lógica de funcionalidad que se ejecuta bajo el control de Common Language Runtime (CLR) de .NET. Un ensamblado existe físicamente como un archivo .dll o como un archivo .exe. Sin embargo, internamente un ensamblado es muy diferente de un archivo DLL de Microsoft Win32.Un archivo de ensamblado contiene un manifiesto de ensamblado, metadatos de tipo, código de lenguaje intermedio de Microsoft (MSIL) y otros recursos. El manifiesto del ensamblado contiene los metadatos del ensamblado que proporcionan toda la información necesaria para que un ensamblado se describa por sí mismo. La siguiente información se incluye en el manifiesto del ensamblado:
  • Nombre del ensamblado
  • Información de la versión
  • Información sobre cultura
  • Información de nombres fuertes
  • La lista de ensamblados de archivos
  • Escriba información de referencia
  • Información de ensamblaje referenciada y dependiente
El código MSIL contenido en el ensamblado no se puede ejecutar directamente. En su lugar, la ejecución de código MSIL se administra a través de CLR. De forma predeterminada, al crear un ensamblado, el ensamblado es privado para la aplicación. Para crear un ensamblado compartido es necesario asignar un nombre seguro al ensamblado y, a continuación, publicar el ensamblado en la caché global de ensamblados.En la lista siguiente se describen algunas de las características de los ensamblados en comparación con las características de los archivos DLL de Win32:
  • Autodescriptivo Al crear un ensamblado, toda la información necesaria para que CLR ejecute el ensamblado se encuentra en el manifiesto del ensamblado. El manifiesto del ensamblado contiene una lista de los ensamblados dependientes. Por lo tanto, CLR puede mantener un conjunto coherente de ensamblados que se usan en la aplicación. En los archivos DLL de Win32, no se puede mantener la coherencia entre un conjunto de archivos DLL que se usan en una aplicación cuando se usan archivos DLL compartidos.
  • Versionado En un manifiesto de ensamblado, CLR registra y aplica la información de versión. Además, las directivas de versión le permiten aplicar el uso específico de la versión. En los archivos DLL de Win32, el sistema operativo no puede aplicar el control de versiones. En su lugar, debe asegurarse de que los archivos DLL son compatibles con versiones anteriores.
  • Despliegue en paralelo Los ensamblados admiten la implementación en paralelo. Una aplicación puede usar una versión de un ensamblado y otra aplicación puede usar una versión diferente de un ensamblado. A partir de Windows 2000, la implementación en paralelo se admite mediante la ubicación de archivos DLL en la carpeta de la aplicación. Además, Protección de archivos de Windows impide que los archivos DLL del sistema se sobrescriban o reemplacen por un agente no autorizado.
  • Autocontención y aislamiento Una aplicación que se desarrolla mediante un ensamblado puede ser independiente y aislada de otras aplicaciones que se ejecutan en el equipo. Esta característica le ayuda a crear instalaciones de impacto cero.
  • Ejecución Un ensamblado se ejecuta bajo los permisos de seguridad que se proporcionan en el manifiesto del ensamblado y que son controlados por CLR.
  • Independiente del idioma Un ensamblado se puede desarrollar mediante cualquiera de los lenguajes .NET admitidos. Por ejemplo, puede desarrollar un ensamblado en Microsoft Visual C y, a continuación, usar el ensamblado en un proyecto de Microsoft Visual Basic .NET.

Referencias


Para obtener más información acerca de los archivos DLL y los ensamblados de .NET Framework, visite los siguientes sitios Web de Microsoft:
Conflictos de DLLImplementación de uso compartido decomponentes enparalelo en aplicacionesCómo crear y dar servicio a aplicaciones aisladas y ensamblados en paralelo para Windows XPSimplificación de la implementación y resolución deconflictos de DLL con .NET FrameworkGuía del desarrollador de.NET Framework: EnsamblajesVinculación dinámicaen tiempo de ejecución almacenamiento local desubprocesos