Wat een DLL is

In dit artikel wordt beschreven wat een Dynamic Link Library (DLL) is en welke problemen kunnen optreden wanneer u DLL's gebruikt. Het beschrijft ook enkele geavanceerde problemen waarmee u rekening moet houden bij het ontwikkelen van uw eigen DLL's.

Van toepassing op: Windows 10, alle edities
Origineel KB-nummer: 815065

Samenvatting

Bij de beschrijving van wat een DLL is, worden in dit artikel dynamische koppelingsmethoden, DLL-afhankelijkheden, DLL-ingangspunten, exporterende DLL-functies en hulpprogramma's voor het oplossen van problemen met DLL's beschreven.

Dit artikel eindigt met een vergelijking op hoog niveau van DLL's met de Microsoft .NET Framework-assembly's.

Voor de Windows-besturingssystemen wordt een groot deel van de functionaliteit van het besturingssysteem geleverd door DLL. Bovendien, wanneer u een programma uitvoert op een van deze Windows-besturingssystemen, kan een groot deel van de functionaliteit van het programma worden geleverd door DLL's. Sommige programma's kunnen bijvoorbeeld veel verschillende modules bevatten en elke module van het programma is opgenomen en gedistribueerd in DLL's.

Het gebruik van DLL's helpt bij het bevorderen van modularisatie van de code, hergebruik van de code, efficiënt geheugengebruik en verminderde schijfruimte. Het besturingssysteem en de programma's laden dus sneller, werken sneller en nemen minder schijfruimte in beslag op de computer.

Wanneer een programma een DLL gebruikt, kan een probleem dat afhankelijkheid wordt genoemd ertoe leiden dat het programma niet wordt uitgevoerd. Wanneer een programma een DLL gebruikt, wordt er een afhankelijkheid gemaakt. Als een ander programma deze afhankelijkheid overschrijft en verbreekt, wordt het oorspronkelijke programma mogelijk niet uitgevoerd.

Met de introductie van het .NET Framework zijn de meeste afhankelijkheidsproblemen geëlimineerd door het gebruik van assembly's.

Meer informatie

Een DLL is een bibliotheek die code en gegevens bevat die door meer dan één programma tegelijk kunnen worden gebruikt. In Windows-besturingssystemen voert de Comdlg32 DLL bijvoorbeeld algemene dialoogvenstergerelateerde functies uit. Elk programma kan de functionaliteit in deze DLL gebruiken om een Open dialoogvenster te implementeren. Het helpt bij het hergebruik van code en efficiënt geheugengebruik.

Door een DLL te gebruiken, kan een programma worden gemoduleerd in afzonderlijke onderdelen. Een boekhoudprogramma kan bijvoorbeeld per module worden verkocht. Elke module kan tijdens runtime in het hoofdprogramma worden geladen als die module is geïnstalleerd. Doordat de modules gescheiden zijn, is de laadtijd van het programma sneller. En een module wordt alleen geladen wanneer deze functionaliteit wordt aangevraagd.

Bovendien zijn updates gemakkelijker toe te passen op elke module zonder andere delen van het programma te beïnvloeden. U heeft bijvoorbeeld een salarisprogramma en de belastingtarieven veranderen elk jaar. Wanneer deze wijzigingen zijn geïsoleerd in een DLL, kunt u een update toepassen zonder dat u het hele programma opnieuw hoeft te bouwen of te installeren.

De volgende lijst beschrijft enkele van de bestanden die zijn geïmplementeerd als DLL's in Windows-besturingssystemen:

  • ActiveX-besturingselementen (.ocx) bestanden

    Een voorbeeld van een ActiveX-besturingselement is een besturingselement voor een agenda waarmee u een datum uit een agenda kunt selecteren.

  • Configuratiescherm (.cpl)-bestanden

    Een voorbeeld van een CPL-bestand is een item dat zich in het Configuratiescherm bevindt. Elk item is een gespecialiseerde DLL.

  • Apparaatstuurprogramma (.drv)-bestanden

    Een voorbeeld van een apparaatstuurprogramma is een printerstuurprogramma dat het afdrukken naar een printer regelt.

DLL-voordelen

De volgende lijst beschrijft enkele van de voordelen die worden geboden wanneer een programma een DLL gebruikt:

  • Maakt gebruik van minder resources

    Wanneer meerdere programma's dezelfde bibliotheek met functies gebruiken, kan een DLL de duplicatie van code die op de schijf en in het fysieke geheugen wordt geladen, verminderen. Het kan een grote invloed hebben op de prestaties van niet alleen het programma dat op de voorgrond wordt uitgevoerd, maar ook van andere programma's die op het Windows-besturingssysteem worden uitgevoerd.

  • Bevordert de modulaire architectuur

    Een DLL helpt bij het ontwikkelen van modulaire programma's. Het helpt u bij het ontwikkelen van grote programma's waarvoor meerdere taalversies nodig zijn of een programma dat een modulaire architectuur vereist. Een voorbeeld van een modulair programma is een boekhoudprogramma met veel modules die tijdens runtime dynamisch kunnen worden geladen.

  • Vereenvoudigt de implementatie en installatie

    Wanneer een functie binnen een DLL een update of een oplossing nodig heeft, hoeft het programma voor de implementatie en installatie van de DLL niet opnieuw te worden gekoppeld aan de DLL. Als meerdere programma's dezelfde DLL gebruiken, zullen meerdere programma's allemaal profiteren van de update of de oplossing. Dit probleem kan vaker optreden wanneer u een DLL van derden gebruikt die regelmatig wordt bijgewerkt of opgelost.

DLL-afhankelijkheden

Wanneer een programma of een DLL een DLL-functie in een andere DLL gebruikt, wordt er een afhankelijkheid gemaakt. Het programma is niet langer zelfstandig en het programma kan problemen ondervinden als de afhankelijkheid is verbroken. Het programma kan bijvoorbeeld niet worden uitgevoerd als een van de volgende acties plaatsvindt:

  • Een afhankelijke DLL wordt geüpgraded naar een nieuwe versie.
  • Een afhankelijke DLL is opgelost.
  • Een afhankelijke DLL wordt overschreven met een eerdere versie.
  • Een afhankelijke DLL wordt van de computer verwijderd.

Deze acties worden DLL-conflicten genoemd. Als compatibiliteit met eerdere versies niet wordt afgedwongen, wordt het programma mogelijk niet uitgevoerd.

De volgende lijst beschrijft de wijzigingen die zijn aangebracht in Windows 2000 en latere Windows-besturingssystemen om afhankelijkheidsproblemen te minimaliseren:

  • Windows Bestandsbeveiliging

    In Windows Bestandsbeveiliging voorkomt het besturingssysteem dat systeem-DLL's worden bijgewerkt of verwijderd door een onbevoegde agent. Wanneer een programma-installatie probeert een DLL te verwijderen of bij te werken die is gedefinieerd als een systeem-DLL, zoekt Windows Bestandsbeveiliging naar een geldige digitale handtekening.

  • Privé-DLL's

    Met privé-DLL's kunt u een programma isoleren van wijzigingen die zijn aangebracht in gedeelde DLL's. Privé-DLL's gebruiken versiespecifieke informatie of een leeg .local bestand om de versie van de DLL die door het programma wordt gebruikt af te dwingen. Als u privé-DLL's wilt gebruiken, zoekt u de DLL's in de hoofdmap van het programma. Voeg vervolgens voor nieuwe programma's versiespecifieke informatie toe aan de DLL. Gebruik voor oude programma's een leeg .local bestand. Elke methode vertelt het besturingssysteem om de privé-DLL's te gebruiken die zich in de hoofdmap van het programma bevinden.

Hulpprogramma's voor het oplossen van problemen met DLL

Er zijn verschillende hulpprogramma's beschikbaar waarmee u DLL-problemen kunt oplossen. De volgende hulpprogramma's zijn enkele van deze hulpprogramma's.

Dependency Walker

Het hulpprogramma Dependency Walker kan recursief scannen naar alle afhankelijke DLL's die door een programma worden gebruikt. Wanneer u een programma opent in Dependency Walker, voert Dependency Walker de volgende controles uit:

  • Dependency Walker controleert op ontbrekende DLL's.
  • De Dependency Walker controleert op ongeldige programmabestanden of DLL's.
  • De Dependency Walker controleert of importfuncties en exportfuncties overeenkomen.
  • De Dependency Walker controleert op circulaire afhankelijkheidsfouten.
  • De Dependency Walker controleert op modules die niet geldig zijn omdat de modules voor een ander besturingssysteem zijn.

Door Dependency Walker te gebruiken, kunt u alle DLL's documenteren die een programma gebruikt. Het kan helpen bij het voorkomen en corrigeren van DLL-problemen die zich in de toekomst kunnen voordoen. De Dependency Walker bevindt zich in de volgende map wanneer u Visual Studio 6.0 installeert:

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

DLL Universal Problem Solver

Het hulpprogramma DLL Universal Problem Solver (DUPS) wordt gebruikt om DLL-gegevens te controleren, te vergelijken, te documenten en weer te geven. In de volgende lijst worden de hulpprogramma's beschreven waaruit het hulpprogramma DUPS bestaat:

  • Dlister.exe

    Dit hulpprogramma somt alle DLL's op de computer op en logt de informatie in een tekstbestand of een databasebestand.

  • Dcomp.exe

    Dit hulpprogramma vergelijkt de DLL's die in twee tekstbestanden worden vermeld en produceert een derde tekstbestand dat de verschillen bevat.

  • Dtxt2DB.exe

    Dit hulpprogramma laadt de tekstbestanden die zijn gemaakt met het hulpprogramma Dlister.exe en het hulpprogramma Dcomp.exe in de dllHell-database.

  • DlgDtxt2DB.exe

    Dit hulpprogramma biedt een grafische gebruikersinterface (GUI)-versie van het hulpprogramma Dtxt2DB.exe.

DLL Help-database

De DLL Help-database helpt u bij het vinden van specifieke versies van DLL's die zijn geïnstalleerd door Microsoft-softwareproducten.

DLL-ontwikkeling

In dit gedeelte worden de problemen en vereisten beschreven waarmee u rekening moet houden wanneer u uw eigen DLL's ontwikkelt.

Typen DLL's

Wanneer u een DLL in een toepassing laadt, kunt u met twee koppelingsmethoden de geëxporteerde DLL-functies aanroepen. De twee methoden van koppelen zijn dynamisch koppelen tijdens laadtijd en dynamisch koppelen tijdens runtime.

Dynamisch koppelen tijdens laadtijd

Bij dynamisch koppelen tijdens laadtijd doet een toepassing expliciete aanroepen naar geëxporteerde DLL-functies, zoals lokale functies. Als u dynamisch koppelen tijdens laadtijd wilt gebruiken, moet u een koptekstbestand (.h) en een importbibliotheekbestand (.lib) opgeven wanneer u de toepassing compileert en koppelt. Wanneer u dit doet, zal de linker het systeem voorzien van de informatie die nodig is om de DLL te laden en de geëxporteerde DLL-functielocaties op te lossen tijdens het laden.

Dynamische runtimekoppeling

Bij dynamische runtimekoppeling roept een toepassing de functie LoadLibrary of de functie LoadLibraryEx aan om de DLL tijdens runtime te laden. Nadat de DLL is geladen, gebruikt u de functie GetProcAddress om het adres te verkrijgen van de geëxporteerde DLL-functie die u wilt aanroepen. Wanneer u dynamische runtimekoppeling gebruikt, hebt u geen importbibliotheekbestand nodig.

In de volgende lijst worden de toepassingscriteria beschreven voor het gebruik van dynamisch koppelen tijdens laadtijd en wanneer dynamische runtimekoppeling worden gebruikt:

  • Opstartprestaties

    Als de initiële opstartprestaties van de toepassing belangrijk zijn, moet u dynamische runtimekoppeling gebruiken.

  • Gebruiksgemak

    Bij dynamisch koppelen tijdens laadtijd zijn de geëxporteerde DLL-functies als lokale functies. Hierdoor kunt u deze functies eenvoudig aanroepen.

  • Toepassingslogica

    Bij dynamische runtimekoppeling kan een toepassing vertakken om verschillende modules naar behoefte te laden. Het is belangrijk wanneer u versies met meerdere talen ontwikkelt.

Het DLL-toegangspunt

Wanneer u een DLL maakt, kunt u optioneel een toegangspuntfunctie specificeren. De toegangspuntfunctie wordt aangeroepen wanneer processen of threads zich hechten aan de DLL of zich losmaken van de DLL. U kunt de toegangspuntfunctie gebruiken om gegevensstructuren te initialiseren of om gegevensstructuren te vernietigen, zoals vereist door de DLL. Als de toepassing multithreaded is, kunt u bovendien lokale threadopslag (TLS) gebruiken om privé-geheugen toe te wijzen aan elke thread in de toegangspuntfunctie. De volgende code is een voorbeeld van de DLL-toegangspuntfunctie.

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;
}

Wanneer de toegangspuntfunctie een ONWAAR-waarde retourneert, zal de toepassing niet starten als u dynamisch koppelen tijdens laadtijd gebruikt. Als u dynamische runtimekoppeling gebruikt, wordt alleen de afzonderlijke DLL niet geladen.

De toegangspuntfunctie mag alleen eenvoudige initialisatietaken uitvoeren en mag geen andere DLL-laad- of beëindigingsfuncties aanroepen. In de toegangspuntfunctie mag u bijvoorbeeld niet direct of indirect de functie LoadLibrary of de functie LoadLibraryEx aanroepen. Bovendien moet u de functie FreeLibrary niet aanroepen wanneer het proces wordt beëindigd.

Opmerking

Zorg er in toepassingen met meerdere threads voor dat de toegang tot de globale DLL-gegevens is gesynchroniseerd (thread safe) om mogelijke gegevensbeschadiging te voorkomen. Gebruik hiervoor TLS om voor elke thread unieke gegevens te verstrekken.

DLL-functies exporteren

Als u DLL-functies wilt exporteren, kunt u een trefwoord voor een functie toevoegen aan de geëxporteerde DLL-functies of een moduledefinitiebestand (.def) maken waarin de geëxporteerde DLL-functies worden vermeld.

Als u een trefwoord voor een functie wilt gebruiken, moet u elke functie declareren die u wilt exporteren met het volgende trefwoord:
__declspec(dllexport)

Als u geëxporteerde DLL-functies in de toepassing wilt gebruiken, moet u elke functie die u wilt importeren declareren met het volgende trefwoord: __declspec(dllimport)

Normaal gesproken gebruikt u één headerbestand met een definitie-instructie en een ifdef-instructie om de export-instructie en de import-instructie te scheiden.

U kunt ook een bestand voor moduledefinitie gebruiken om geëxporteerde DLL-functies te declareren. Wanneer u een bestand voor moduledefinitie gebruikt, hoeft u het trefwoord voor de functie niet toe te voegen aan de geëxporteerde DLL-functies. In het bestand voor moduledefinitie declareert u de LIBRARY-instructie en de EXPORTS-instructie voor het DLL-bestand. De volgende code is een voorbeeld van een definitiebestand.

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

Voorbeeld van een DLL en toepassing

In Visual C++ 6.0 kunt u een DLL maken door het projecttype Win32 Dynamic-Link Library of het projecttype MFC AppWizard (dll) te selecteren.

De volgende code is een voorbeeld van een DLL die is gemaakt in Visual C++ met behulp van het projecttype 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

De volgende code is een voorbeeld van een project met Win32-toepassing dat de geëxporteerde DLL-functie in de SampleDLL DLL aanroept.

// SampleApp.cpp
//
#include "stdafx.h"
#include "sampleDLL.h"
int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
    HelloWorld();
    return 0;
}

Opmerking

Bij dynamisch koppelen tijdens laadtijd moet u de SampleDLL.lib-importbibliotheek koppelen die is gemaakt wanneer u het SampleDLL-project bouwt.

Bij dynamische runtimekoppeling gebruikt u een code die vergelijkbaar is met de volgende code om de geëxporteerde DLL-functie SampleDLL.dll aan te roepen.

...
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);
}
...

Wanneer u de SampleDLL-toepassing compileert en koppelt, zoekt het Windows-besturingssysteem naar de SampleDLL DLL op de volgende locaties in deze volgorde:

  1. De toepassingsmap

  2. De huidige map

  3. De Windows-systeemmap

    Opmerking

    De functie GetSystemDirectory retourneert het pad van de Windows-systeemmap.

  4. De map Windows

    Opmerking

    De functie GetWindowsDirectory retourneert het pad van de map Windows.

De .NET Framework-assembly

Met de introductie van .NET en het .NET Framework zijn de meeste problemen die gepaard gaan met DLL's geëlimineerd door het gebruik van assembly's.. Een assembly is een logische eenheid van functionaliteit die wordt beheerd door de NET Common Language Runtime (CLR). Een assembly bestaat fysiek als een dll-bestand of als een exe-bestand. Intern is een assembly echter anders dan een Microsoft Win32 DLL.

Een assembly-bestand bevat een assembly-manifest, type metagegevens, Microsoft Intermediate Language (MSIL)-code en andere bronnen. Het assembly-manifest bevat de metagegevens van de assembly die alle informatie bevat die nodig is om een assembly zelfbeschrijvend te maken. De volgende informatie is opgenomen in het assembly-manifest:

  • Assembly-naam
  • Versiegegevens
  • Cultuurinformatie
  • Sterke naaminformatie
  • De assembly-lijst met bestanden
  • Type referentie-informatie
  • Gerefereerde en afhankelijke assembly-informatie

De MSIL-code die zich in de assembly bevindt, kan niet rechtstreeks worden uitgevoerd. In plaats daarvan wordt de uitvoering van MSIL-code beheerd via de CLR. Wanneer u een assembly maakt, is de assembly standaard privé voor de toepassing. Om een gedeelde assembly te maken, moet u een sterke naam aan de assembly toewijzen en de assembly vervolgens publiceren in de globale assembly-cache.

De volgende lijst beschrijft enkele functies van assembly's in vergelijking met de functies van Win32-DLL's:

  • Zelfbeschrijvend

    Wanneer u een assembly maakt, bevat het assembly-manifest alle informatie die nodig is voor de CLR om de assembly uit te voeren. Het assembly-manifest bevat een lijst met de afhankelijke assembly's. Daarom kan de CLR een consistente set assembly's onderhouden die in de toepassing worden gebruikt. In Win32-DLL's kunt u geen consistentie handhaven tussen een set DLL's die in een toepassing worden gebruikt wanneer u gedeelde DLL's gebruikt.

  • Versiebeheer

    In een assembly-manifest wordt versiegegevens vastgelegd en gehandhaafd door de CLR. Bovendien kunt u met versiebeleid versiespecifiek gebruik afdwingen. In Win32-DLL's kan versiebeheer niet worden afgedwongen door het besturingssysteem. U moet ervoor zorgen dat DLL's achterwaarts compatibel zijn.

  • Implementatie naast elkaar

    Assembly's ondersteunen implementatie naast elkaar. Eén toepassing kan één versie van een assembly gebruiken en een andere toepassing kan een andere versie van een assembly gebruiken. Vanaf Windows 2000 wordt implementatie naast elkaar ondersteund door DLL's in de toepassingsmap te zoeken. Bovendien voorkomt Windows Bestandsbeveiliging dat systeem-DLL's worden overschreven of vervangen door een niet-geautoriseerde agent.

  • Zelf-containment en isolatie

    Een toepassing die is ontwikkeld met behulp van een assembly kan op zichzelf staan en geïsoleerd zijn van andere toepassingen die op de computer worden uitgevoerd. Deze functie helpt u bij het maken van installaties zonder impact.

  • Uitvoering

    Een assembly wordt uitgevoerd onder de beveiligingsmachtigingen die zijn opgegeven in het assembly-manifest en die worden beheerd door de CLR.

  • Taalonafhankelijk

    Een assembly kan worden ontwikkeld door een van de ondersteunde .NET-talen te gebruiken. U kunt bijvoorbeeld een assembly ontwikkelen in Microsoft Visual C# en de assembly vervolgens gebruiken in een Visual Basic .NET-project.

Gegevensverzameling

Als u hulp nodig hebt van Microsoft-ondersteuning, raden we u aan de informatie te verzamelen door de stappen te volgen die worden vermeld in Informatie verzamelen met behulp van TSS voor implementatiegerelateerde problemen.

Verwijzingen