Vad en DLL är

Den här artikeln beskriver vad ett dynamiskt länkbibliotek (DLL) är och de olika problem som kan uppstå när du använder DLL:er. Den beskriver också några avancerade problem som du bör tänka på när du utvecklar dina egna DLL:er.

Gäller för: Windows 10 – alla versioner
Original-KB-nummer: 815065

Sammanfattning

För att beskriva vad en DLL är, beskriver den här artikeln dynamiska länkningsmetoder, DLL-beroenden, DLL-ingångspunkter, exporterande DLL-funktioner och DLL-felsökningsverktyg.

Den här artikeln avslutas med en övergripande jämförelse av DLL:er med Microsoft .NET Framework-sammansättningar.

För Windows-operativsystem tillhandahålls mycket av operativsystemets funktioner av DLL. När du kör ett program på något av dessa Windows-operativsystem kan dessutom mycket av programmets funktioner tillhandahållas av DLL:er. Vissa program kan till exempel innehålla många olika moduler, och varje modul i programmet finns och distribueras i DLL:er.

Användningen av DLL:er bidrar till att främja modularisering av kod, återanvändning av kod, effektiv minnesanvändning och minskat diskutrymme. Operativsystemet och programmen läses därför in snabbare, körs snabbare och tar mindre diskutrymme på datorn.

När ett program använder en DLL kan ett problem som kallas "beroende" orsaka att programmet inte körs. När ett program använder en DLL skapas ett beroende. Om ett annat program skriver över och bryter det här beroendet kanske det ursprungliga programmet inte körs.

I och med introduktionen av .NET Framework har de flesta beroendeproblem eliminerats med hjälp av sammansättningar.

Mer information

En DLL är ett bibliotek som innehåller kod och data som kan användas av mer än ett program samtidigt. I Windows-operativsystem utför till exempel Comdlg32 DLL vanliga dialogrutarelaterade funktioner. Varje program kan använda de funktioner som finns i den här DLL:en för att implementera dialogrutan Öppna. Det bidrar till att främja återanvändning av kod och effektiv minnesanvändning.

Genom att använda en DLL kan ett program modulariseras till separata komponenter. Ett redovisningsprogram kan till exempel säljas via modul. Varje modul kan läsas in i huvudprogrammet vid körning om modulen är installerad. Eftersom modulerna är separata är programmets inläsningstid snabbare. Och en modul läses bara in när den funktionen begärs.

Dessutom är uppdateringar enklare att tillämpa på varje modul utan att påverka andra delar av programmet. Du kan till exempel ha ett löneprogram och momssatserna ändras varje år. När dessa ändringar är isolerade till en DLL kan du tillämpa en uppdatering utan att behöva skapa eller installera hela programmet igen.

I följande lista beskrivs några av de filer som implementeras som DLL:er i Windows-operativsystem:

  • ActiveX-kontrollfiler (.ocx)

    Ett exempel på en ActiveX-kontroll är en kalenderkontroll där du kan välja ett datum från en kalender.

  • Kontrollpanelsfiler (.cpl)

    Ett exempel på en .cpl-fil är ett objekt som finns i Kontrollpanelen. Varje objekt är en specialiserad DLL.

  • Drivrutinsfiler (.drv).

    Ett exempel på en enhetsdrivrutin är en skrivardrivrutin som styr utskriften till en skrivare.

DLL-fördelar

I följande lista beskrivs några av de fördelar som ges när ett program använder en DLL:

  • Använder färre resurser

    När flera program använder samma bibliotek med funktioner kan en DLL minska dupliceringen av kod som läses in på disken och i det fysiska minnet. Det kan i hög grad påverka prestandan för inte bara det program som körs i förgrunden, utan även andra program som körs på Windows-operativsystem.

  • Främjar modulär arkitektur

    En DLL hjälper till att främja utveckling av modulära program. Det hjälper dig att utveckla stora program som kräver flera språkversioner eller ett program som kräver modulär arkitektur. Ett exempel på ett modulärt program är ett redovisningsprogram som har många moduler som kan läsas in dynamiskt vid körning.

  • Underlättar distribution och installation

    När en funktion i en DLL behöver en uppdatering eller en korrigering kräver inte distributionen och installationen av DLL:en att programmet länkas om med DLL:en. Om flera program använder samma DLL kan dessutom flera program dra nytta av uppdateringen eller korrigeringen. Det här problemet kan inträffa oftare när du använder en DLL från tredje part som uppdateras eller åtgärdas regelbundet.

DLL-beroenden

När ett program eller en DLL använder en DLL-funktion i en annan DLL skapas ett beroende. Programmet är inte längre fristående och programmet kan uppleva problem om beroendet bryts. Programmet kanske till exempel inte körs om någon av följande åtgärder inträffar:

  • En beroende DLL uppgraderas till en ny version.
  • En beroende DLL är fast.
  • En beroende DLL skrivs över med en tidigare version.
  • En beroende DLL tas bort från datorn.

Dessa åtgärder kallas DLL-konflikter. Om bakåtkompatibilitet inte tillämpas kanske programmet inte körs.

I följande lista beskrivs de ändringar som har införts i Windows 2000 och senare Windows-operativsystem för att minimera beroendeproblem:

  • Windows-filskydd

    I Windows-filskydd förhindrar operativsystemet att system-DLL:er uppdateras eller tas bort av en obehörig agent. När en programinstallation försöker ta bort eller uppdatera en DLL som definieras som en system-DLL letar Windows-filskydd efter en giltig digital signatur.

  • Privata DLL:er

    Med privata DLL:er kan du isolera ett program från ändringar som görs i delade DLL:er. Privata DLL:er använder versionsspecifik information eller en tom .local-fil för att framtvinga den version av DLL som används av programmet. Om du vill använda privata DLL:er letar du upp dina DLL:er i programmets rotmapp. För nya program lägger du sedan till versionsspecifik information i DLL-filen. Använd en tom .local-fil för gamla program. Varje metod instruerar operativsystemet att använda de privata DLL:er som finns i programmets rotmapp.

Felsökningsverktyg för DLL

Det finns flera verktyg som hjälper dig att felsöka DLL-problem. Följande verktyg är några av dessa verktyg.

Beroendevandrare

Verktyget Beroendevandrare kan rekursivt söka efter alla beroende DLL:er som används av ett program. När du öppnar ett program i Beroendevandrare gör Beroendevandrare följande kontroller:

  • Beroendevandrare söker efter saknade DLL:er.
  • Beroendevandrare söker efter programfiler eller DLL:er som inte är giltiga.
  • Beroendevandrare kontrollerar att importfunktioner och exportfunktioner matchar.
  • Beroendevandrare söker efter cirkulära beroendefel.
  • Beroendevandrare söker efter moduler som inte är giltiga eftersom modulerna är för ett annat operativsystem.

Med Beroendevandrare kan du dokumentera alla DLL:er som ett program använder. Det kan hjälpa till att förhindra och korrigera DLL-problem som kan uppstå i framtiden. Beroendevandrare finns i följande katalog när du installerar Visual Studio 6.0:

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

Universal problemlösare för DLL

Verktyget Universal problemlösare för DLL (DUPS) används för att granska, jämföra, dokumentera och visa DLL-information. I följande lista beskrivs de verktyg som utgör DUPS-verktyget:

  • Dlister.exe

    Det här verktyget räknar upp alla DLL:er på datorn och loggar informationen till en textfil eller till en databasfil.

  • Dcomp.exe

    Det här verktyget jämför DLL:er som visas i två textfiler och skapar en tredje textfil som innehåller skillnaderna.

  • Dtxt2DB.exe

    Det här verktyget läser in textfilerna som skapas med hjälp av verktyget Dlister.exe och verktyget Dcomp.exe i dllHell-databasen.

  • DlgDtxt2DB.exe

    Det här verktyget tillhandahåller en grafisk användargränssnittsversion (GUI) av Dtxt2DB.exe-verktyget.

DLL-hjälpdatabas

DLL-hjälpdatabasen hjälper dig att hitta specifika versioner av DLL:er som installeras av Microsofts programvaruprodukter.

DLL-utveckling

I det här avsnittet beskrivs de problem och krav som du bör tänka på när du utvecklar egna DLL:er.

Typer av DLL:er

När du läser in en DLL i ett program kan du med två länkningsmetoder anropa de exporterade DLL-funktionerna. De två metoderna för länkning är dynamisk länkning för inläsningstid och dynamisk länkning vid körning.

Dynamisk länkning för inläsningstid

I dynamisk länkning för inläsningstid gör ett program explicita anrop till exporterade DLL-funktioner som lokala funktioner. Om du vill använda dynamisk länkning för inläsningstid anger du en rubrikfil (.h) och en importbiblioteksfil (.lib) när du kompilerar och länkar programmet. När du gör detta ger länkaren systemet den information som krävs för att läsa in DLL-filen och lösa de exporterade DLL-funktionsplatserna vid inläsningen.

Dynamisk länkning vid körning

I dynamisk länkning vid körning anropar ett program antingen funktionen LoadLibrary eller funktionen LoadLibraryEx för att läsa in DLL-filen vid körning. När DLL-filen har lästs in använder du funktionen GetProcAddress för att hämta adressen till den exporterade DLL-funktion som du vill anropa. När du använder dynamisk länkning vid körning behöver du ingen importbiblioteksfil.

Följande lista beskriver tillämpningskriterierna för när du ska använda dynamisk länkning för inläsningstid och när du ska använda dynamisk länkning vid körning:

  • Startprestanda

    Om programmets startprestanda är viktig bör du använda dynamisk länkning vid körning.

  • Användarvänlighet

    I dynamisk länkning vid inläsningstid är de exporterade DLL-funktionerna som lokala funktioner. Det gör det enkelt för dig att anropa dessa funktioner.

  • Programlogik

    I dynamisk länkning vid körning kan ett program förgrena sig för att läsa in olika moduler efter behov. Det är viktigt när du utvecklar versioner med flera språk.

Startpunkten för DLL

När du skapar en DLL kan du ange en startpunktsfunktion. Startpunktsfunktionen anropas när processer eller trådar kopplar sig till DLL:en eller kopplar sig från DLL-filen. Du kan använda startpunktsfunktionen för att initiera datastrukturer eller förstöra datastrukturer som krävs av DLL:en. Om programmet är flertrådat kan du dessutom använda trådlokal lagring (TLS) för att allokera minne som är privat för varje tråd i startpunktsfunktionen. Följande kod är ett exempel på DLL-startpunktsfunktionen.

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

När startpunktsfunktionen returnerar ett FALSKT värde startar inte programmet om du använder dynamisk länkning för inläsningstid. Om du använder dynamisk länkning vid körning läses endast den enskilda DLL-filen in.

Startpunktsfunktionen ska bara utföra enkla initieringsuppgifter och ska inte anropa andra DLL-inläsnings- eller avslutningsfunktioner. I startpunktsfunktionen bör du till exempel inte direkt eller indirekt anropa funktionen LoadLibrary eller funktionen LoadLibraryEx. Dessutom bör du inte anropa funktionen FreeLibrary när processen avslutas.

Obs!

Se till att åtkomsten till globala DLL-data synkroniseras (trådsäkert) i flertrådsprogram för att undvika eventuella skadade data. Det gör du genom att använda TLS för att tillhandahålla unika data för varje tråd.

Exportera DLL-funktioner

Om du vill exportera DLL-funktioner kan du antingen lägga till ett funktionsnyckelord i de exporterade DLL-funktionerna eller skapa en moduldefinitionsfil (.def) som visar de exporterade DLL-funktionerna.

Om du vill använda ett funktionsnyckelord måste du deklarera varje funktion som du vill exportera med följande nyckelord:
__declspec(dllexport)

Om du vill använda exporterade DLL-funktioner i programmet måste du deklarera varje funktion som du vill importera med följande nyckelord: __declspec(dllimport)

Vanligtvis använder du en rubrikfil som har en definierad instruktion och en ifdef-instruktion för att separera exportinstruktionen och instruktionen import.

Du kan också använda en moduldefinitionsfil för att deklarera exporterade DLL-funktioner. När du använder en moduldefinitionsfil behöver du inte lägga till funktionsnyckelordet i de exporterade DLL-funktionerna. I moduldefinitionsfilen deklarerar du instruktionen LIBRARY och instruktionen EXPORTS för DLL:en. Följande kod är ett exempel på en definitionsfil.

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

Exempel-DLL och program

I Visual C++ 6.0 kan du skapa en DLL genom att välja projekttypen Win32 Dynamic-Link Library eller projekttypen MFC AppWizard (dll).

Följande kod är ett exempel på en DLL som skapades i Visual C++ med projekttypen 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

Följande kod är ett exempel på ett Win32-programprojekt som anropar den exporterade DLL-funktionen i SampleDLL DLL.

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

Obs!

I dynamisk länkning för inläsningstid måste du länka importbiblioteket SampleDLL.lib som skapas när du skapar SampleDLL-projektet.

I dynamisk länkning vid körning använder du en kod som liknar följande kod för att anropa den SampleDLL.dll-exporterade DLL-funktionen.

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

När du kompilerar och länkar SampleDLL-programmet söker Windows-operativsystemet efter SampleDLL DLL på följande platser i den här ordningen:

  1. Programmappen

  2. Den aktuella mappen

  3. Windows-systemmappen

    Obs!

    Funktionen GetSystemDirectory returnerar sökvägen till Windows-systemmappen.

  4. Mappen Windows

    Obs!

    Funktionen GetWindowsDirectory returnerar sökvägen till mappen Windows.

Sammansättningen .NET Framework

I och med introduktionen av .NET och .NET Framework har de flesta problem som är associerade med DLL:er eliminerats med hjälp av sammansättningar. En sammansättning är en logisk funktionsenhet som körs under kontroll av .NET Common Language Runtime (CLR). En sammansättning finns fysiskt som en .dll-fil eller som en .exe-fil. Internt skiljer sig dock en sammansättning från en Microsoft Win32-DLL.

En sammansättningsfil innehåller ett sammansättningsmanifest, typmetadata, Microsofts msil-kod (intermediate language) och andra resurser. Sammansättningsmanifestet innehåller sammansättningsmetadata som innehåller all information som krävs för att en sammansättning ska kunna beskrivas själv. Följande information ingår i sammansättningsmanifestet:

  • Sammansättningsnamn
  • Versionsinformation
  • Kulturinformation
  • Stark namninformation
  • Sammansättningslistan över filer
  • Ange referensinformation
  • Refererad och beroende sammansättningsinformation

MSIL-koden som finns i sammansättningen kan inte köras direkt. I stället hanteras MSIL-kodkörningen via CLR. När du skapar en sammansättning är sammansättningen som standard privat för programmet. För att skapa en delad sammansättning måste du tilldela sammansättningen ett starkt namn och sedan publicera sammansättningen i den globala sammansättningscacheminnet.

I följande lista beskrivs några av sammansättningsfunktionerna jämfört med funktionerna i Win32 DLL:er:

  • Självbeskrivande

    När du skapar en sammansättning finns all information som krävs för att CLR:en ska köra sammansättningen i sammansättningsmanifestet. Sammansättningsmanifestet innehåller en lista över beroende sammansättningar. Därför kan CLR:en upprätthålla en konsekvent uppsättning sammansättningar som används i programmet. I Win32 DLL:er kan du inte upprätthålla överensstämmelse mellan en uppsättning DLL:er som används i ett program när du använder delade DLL:er.

  • Versionshantering

    I ett sammansättningsmanifest registreras versionsinformationen och framtvingas av CLR:en. Dessutom låter versionspolicyer dig tvinga fram versionsspecifik användning. I Win32-DLL:er kan versionshantering inte tillämpas av operativsystemet. Du måste se till att DLL:er är bakåtkompatibla.

  • Sida-vid-sida-distribution

    Sammansättningar stöder sida-vid-sida-distribution. Ett program kan använda en version av en sammansättning och ett annat program kan använda en annan version av en sammansättning. Från och med Windows 2000 stöds sida-vid-sida-distribution genom att hitta DLL:er i programmappen. Dessutom förhindrar Windows filskydd att system-DLL:er skrivs över eller ersätts av en obehörig agent.

  • Självinneslutning och isolering

    Ett program som utvecklas med hjälp av en sammansättning kan vara fristående och isolerat från andra program som körs på datorn. Den här funktionen hjälper dig att skapa nollpåverkande installationer.

  • Utförande

    En sammansättning körs under de säkerhetsbehörigheter som anges i sammansättningsmanifestet och som styrs av CLR:en.

  • Språkoberoende

    En sammansättning kan utvecklas med något av de .NET-språk som stöds. Du kan till exempel utveckla en sammansättning i Microsoft Visual C# och sedan använda sammansättningen i ett Visual Basic .NET-projekt.

Datainsamling

Om du behöver hjälp från Microsofts support rekommenderar vi att du samlar in informationen genom att följa stegen i Samla in information med hjälp av TSS för distributionsrelaterade problem.

Referenser