Qué es una DLL

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 dll. También describe algunos problemas avanzados que debe tener en cuenta al desarrollar sus propias DLL.

Se aplica a:   Windows 10: todas las ediciones
Número KB original:   815065

Resumen

Al describir lo que es un ARCHIVO DLL, en este artículo se describen los métodos de vinculación dinámica, las dependencias 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 dll con los ensamblados de microsoft .NET Framework web.

Para los Windows operativos, dll proporciona gran parte de la funcionalidad del sistema operativo. Además, al ejecutar un programa en uno de estos Windows operativos, gran parte de la funcionalidad del programa puede ser proporcionada por 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 DLL ayuda a promover la modularización del código, la reutilización de código, el uso eficiente de la memoria y el espacio reducido 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 usa un DLL, un problema que se denomina dependencia puede hacer que el programa no se ejecute. Cuando un programa usa un 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 la .NET Framework, la mayoría de los problemas de dependencia se han eliminado mediante ensamblados.

Más información

Un ARCHIVO DLL es una biblioteca que contiene código y datos que puede usar más de un programa al mismo tiempo. Por ejemplo, en Windows operativos, la DLL de Comdlg32 realiza funciones comunes relacionadas con el cuadro de diálogo. Cada programa puede usar la funcionalidad que contiene esta DLL para implementar un cuadro de diálogo Abrir. Ayuda a promover la reutilización de código y el uso eficiente de la memoria.

Al usar una DLL, un programa se puede modular en componentes independientes. Por ejemplo, un programa de contabilidad puede venderse por módulo. Cada módulo se puede cargar en el programa principal en tiempo de ejecución si 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 fiscales 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 siguiente lista se describen algunos de los archivos que se implementan como DLL en Windows sistemas operativos:

  • ActiveX Archivos de controles (.ocx)

    Un ejemplo de un control ActiveX es un control de calendario que 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 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 siguiente lista se describen algunas de las ventajas que se proporcionan cuando un programa usa una DLL:

  • Usa menos recursos

    Cuando varios programas usan la misma biblioteca de funciones, un DLL puede reducir la duplicación de código que se carga en el disco y en la memoria física. Puede influir enormemente en el rendimiento no solo del programa que se ejecuta en primer plano, sino también de otros programas que se ejecutan en el Windows operativo.

  • Promueve la arquitectura modular

    Una DLL ayuda a promover el desarrollo de programas modulares. 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 DLL necesita una actualización o una corrección, la implementación e instalación de la DLL no requiere que el programa se vuelva a vincular con la DLL. Además, si varios programas usan la misma 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 usa un DLL de terceros que se actualiza o se soluciona periódicamente.

Dependencias dll

Cuando un programa o dll usa una función DLL en otra DLL, se crea una dependencia. El programa ya no es independiente 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 ha corregido un DLL dependiente.
  • Un ARCHIVO DLL dependiente se sobrescribe con una versión anterior.
  • Se quita una DLL dependiente del equipo.

Estas acciones se conocen como conflictos dll. Si no se aplica la compatibilidad con versiones anteriores, es posible que el programa no se ejecute correctamente.

En la siguiente lista se describen los cambios que se han introducido en Windows 2000 y en sistemas operativos Windows posteriores para ayudar a minimizar los problemas de dependencia:

  • Windows Protección de archivos

    En Windows de archivos, el sistema operativo impide que un agente no autorizado actualice o elimine las DLL del sistema. Cuando una instalación de programa intenta quitar o actualizar una DLL definida como DLL del sistema, Windows Protección de archivos buscará una firma digital válida.

  • DLL privadas

    Las DLL privadas permiten aislar un programa de los cambios realizados en dll compartidas. Las DLL privadas usan información específica de la versión o un archivo vacío para aplicar la versión de la DLL que usa .local el programa. Para usar dll privadas, busque las DLL en la carpeta raíz del programa. A continuación, para los nuevos programas, agregue información específica de la versión a la DLL. Para los programas antiguos, use un archivo .local vacío. Cada método indica al sistema operativo que use las DLL privadas 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.

Senderista de dependencia

La herramienta Andador de dependencias puede examinar de forma recursiva todas las DLL dependientes que usa un programa. Al abrir un programa en Dependency Walker, Dependency Walker realiza las siguientes comprobaciones:

  • Dependency Walker comprueba si faltan DLL.
  • Dependency Walker busca archivos de programa o DLL que no son válidos.
  • Dependency Walker comprueba que las funciones de importación y exportación coinciden.
  • Dependency Walker comprueba si hay errores de dependencia circular.
  • Dependency Walker busca módulos que no son válidos porque los módulos son para un sistema operativo diferente.

Con Dependency Walker, puede documentar todas las DLL que usa un programa. Puede ayudar a evitar y corregir problemas de DLL que puedan producirse en el futuro. Dependency Walker se encuentra en el siguiente directorio al instalar Visual Studio 6.0:

drive\Program Files\Microsoft Visual Studio\Common\Tools

DLL Universal Problem Solver

La herramienta DLL Universal Problem Solver (DUPS) se usa para auditar, comparar, documentar y mostrar información de DLL. En la siguiente lista se describen las utilidades que forma la herramienta DUPS:

  • Dlister.exe

    Esta utilidad enumera todas las 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 las DLL que se enumeran en dos archivos de texto y produce 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 gráfica de la interfaz de usuario (GUI) de la utilidad Dtxt2DB.exe usuario.

Base de datos de ayuda dll

La base de datos de ayuda de DLL le ayuda a localizar versiones específicas de dll instaladas 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 propias DLL.

Tipos de 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 usar 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 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 o a la función para cargar la LoadLibrary DLL en tiempo de LoadLibraryEx ejecución. Después de cargar correctamente la DLL, se usa la función para obtener la dirección de la función DLL exportada a la GetProcAddress que desea llamar. Al usar la vinculación dinámica en tiempo de ejecución, no necesita un archivo de biblioteca de importación.

En la siguiente lista se describen los criterios de la aplicación para cuándo usar la vinculación dinámica en tiempo de carga y cuándo usar la vinculación dinámica en tiempo de ejecución:

  • Rendimiento de inicio

    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 facilita la llamada a estas funciones.

  • Lógica de 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. Es importante al desarrollar versiones en varios idiomas.

El punto de entrada dll

Al crear una 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 a la DLL o se desasocian de la DLL. Puede usar la función de punto de entrada para inicializar estructuras de datos o para destruir las estructuras de datos según lo requiera la 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 siguiente código es un ejemplo de la función de punto de entrada DLL.

BOOL APIENTRY DllMain(
HANDLE hModule,// Handle to DLL module
DWORD ul_reason_for_call,// Reason for calling function
LPVOID 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 usa la vinculación dinámica en tiempo de carga. Si usa la vinculación dinámica en tiempo de ejecución, solo no se cargará la 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 se debe llamar directa o indirectamente a la LoadLibrary función o a la LoadLibraryEx función. Además, no debe llamar a la FreeLibrary función cuando finalice el proceso.

Nota

En aplicaciones multiproceso, asegúrese de que el acceso a los datos globales 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.

Exportar 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 enumera las funciones DLL exportadas.

Para usar una palabra clave de función, debe declarar cada función que desee exportar con la siguiente palabra clave:
__declspec(dllexport)

Para usar funciones DLL exportadas en la aplicación, debe declarar cada función que desee importar con la siguiente palabra clave: __declspec(dllimport)

Normalmente, se usa un archivo de encabezado que tiene una instrucción define y una ifdef instrucción para separar la instrucción export y la import instrucción.

También puede usar un archivo de definición de módulo para declarar funciones DLL exportadas. Cuando se usa un archivo de definición de módulo, no es necesario agregar la palabra clave de función a las funciones DLL exportadas. En el archivo de definición de módulo, se declara la LIBRARY instrucción y la instrucción de la EXPORTS DLL. El siguiente código es un ejemplo de un archivo de definición.

// SampleDLL.def
//
LIBRARY "sampleDLL"
EXPORTS HelloWorld

DLL de ejemplo y aplicación

En Visual C++ 6.0, puede crear un ARCHIVO DLL seleccionando el tipo de proyecto Biblioteca de Dynamic-Link win32 o el tipo de proyecto Mfc AppWizard (dll).

El siguiente código es un ejemplo de un archivo DLL que se creó en Visual C++ mediante el tipo 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_DLL
        extern __declspec(dllexport) void HelloWorld();
    #else
        extern __declspec(dllimport) void HelloWorld();
    #endif

#endif

El siguiente código es un ejemplo de un proyecto de aplicación de Win32 que llama a la función DLL exportada en el DLL de 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 siguiente código para llamar a la SampleDLL.dll dll exportada.

...
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 DLL de SampleDLL en las siguientes ubicaciones en este orden:

  1. La carpeta de la aplicación

  2. La carpeta actual

  3. La Windows del sistema

    Nota

    La función GetSystemDirectory devuelve la ruta de acceso de Windows carpeta del sistema.

  4. La Windows carpeta

    Nota

    La función GetWindowsDirectory devuelve la ruta de acceso de la Windows carpeta.

El .NET Framework de datos

Con la introducción de .NET y .NET Framework, la mayoría de los problemas asociados con dll se han eliminado mediante ensamblados. Un ensamblado es una unidad lógica de funcionalidad que se ejecuta bajo el control de .NET Common Language Runtime (CLR). Un ensamblado existe físicamente como un archivo .dll o como un archivo .exe archivo. Sin embargo, internamente un ensamblado es diferente de un 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 de ensamblado contiene los metadatos de ensamblado que proporcionan toda la información necesaria para que un ensamblado se describa a sí mismo. La siguiente información se incluye en el manifiesto del ensamblado:

  • Nombre del ensamblado
  • Información de versión
  • Información de referencia cultural
  • Información de nombre sólido
  • La lista de ensamblados de archivos
  • Información de referencia de tipo
  • Información de ensamblado a la que se hace referencia 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 sólido al ensamblado y, a continuación, publicarlo en la memoria caché global de ensamblados.

En la siguiente lista se describen algunas de las características de los ensamblados en comparación con las características de las DLL de Win32:

  • Autodescripto

    Al crear un ensamblado, toda la información necesaria para que CLR ejecute el ensamblado se incluye 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 las DLL de Win32, no se puede mantener la coherencia entre un conjunto de DLL que se usan en una aplicación cuando se usan DLL compartidas.

  • Control de versiones

    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 las DLL de Win32, el sistema operativo no puede aplicar el control de versiones. Debe asegurarse de que las DLL son compatibles con versiones anteriores.

  • Implementación en paralelo

    Los ensamblados admiten la implementación en paralelo. Una aplicación puede usar una versión de un ensamblado y otra puede usar una versión diferente de un ensamblado. A partir Windows 2000, la implementación en paralelo se admite mediante la ubicación de dll en la carpeta de la aplicación. Además, Windows protección de archivos evita que las DLL del sistema se sobrescriban o se reemplazan por un agente no autorizado.

  • Autocontención y aislamiento

    Una aplicación desarrollada 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 están controlados por CLR.

  • Idioma independiente

    Un ensamblado se puede desarrollar mediante cualquiera de los idiomas .NET admitidos. Por ejemplo, puede desarrollar un ensamblado en Microsoft Visual C# y, a continuación, usar el ensamblado en un Visual Basic .NET.

Referencias