Udostępnij za pośrednictwem


Czym jest biblioteka DLL

W tym artykule opisano, czym jest biblioteka linków dynamicznych (DLL) oraz różne problemy, które mogą wystąpić podczas korzystania z bibliotek DLL. Przedstawia również niektóre zaawansowane problemy, które należy wziąć pod uwagę podczas tworzenia własnych bibliotek DLL.

Dotyczy systemu: Windows 10 (wszystkie wersje)
Oryginalny numer KB: 815065

Podsumowanie

W opisie biblioteki DLL w tym artykule przedstawiono metody tworzenia linków dynamicznych, zależności biblioteki DLL, punkty wejścia biblioteki DLL, eksportowanie funkcji biblioteki DLL i narzędzia do rozwiązywania problemów z biblioteką DLL.

Ten artykuł kończy się porównaniem bibliotek DLL wysokiego poziomu z zestawami Microsoft .NET Framework.

W przypadku systemów operacyjnych Windows wiele funkcji systemu operacyjnego jest zapewnianych przez bibliotekę DLL. Ponadto po uruchomieniu programu na jednym z tych systemów operacyjnych Windows większość funkcji programu może być zapewniana przez biblioteki DLL. Na przykład niektóre programy mogą zawierać wiele różnych modułów, a każdy moduł programu jest zawarty i rozpowszechniany w bibliotekach DLL.

Korzystanie z bibliotek DLL pomaga promować modularyzację kodu, ponowne użycie kodu, efektywne wykorzystanie pamięci i zmniejszenie miejsca na dysku. W związku z tym system operacyjny i programy ładują się szybciej, działają szybciej i zajmują mniej miejsca na dysku na komputerze.

Gdy program używa biblioteki DLL, problem zależności może spowodować, że program nie uruchomi się. Gdy program używa biblioteki DLL, powstaje zależność. Jeśli inny program zastępuje i przerywa tę zależność, oryginalny program może nie zostać pomyślnie uruchomiony.

Wraz z wprowadzeniem .NET Framework większość problemów z zależnościami została wyeliminowana przy użyciu zestawów.

Więcej informacji

Biblioteka DLL jest biblioteką zawierającą kod i dane, które mogą być używane przez więcej niż jeden program w tym samym czasie. Na przykład w systemach operacyjnych Windows, plik comdlg32 DLL wykonuje typowe funkcje związane z oknami dialogowymi. Każdy program może użyć funkcji zawartej w tej bibliotece DLL do zaimplementowania okna dialogowego Otwórz. Pomaga promować ponowne użycie kodu i efektywne użycie pamięci.

Za pomocą biblioteki DLL, program może być zmodularyzowany na oddzielne składniki. Na przykład program księgowy może być sprzedawany przez moduł. Każdy moduł można załadować do głównego programu w czasie wykonywania, jeśli ten moduł jest zainstalowany. Ponieważ moduły są oddzielne, czas ładowania programu jest krótszy. Moduł jest ładowany tylko wtedy, gdy żąda się funkcji.

Ponadto aktualizacje są łatwiejsze do zastosowania do każdego modułu bez wpływu na inne części programu. Na przykład może to być program listy płac, a stawki podatku zmieniają się każdego roku. Gdy te zmiany są izolowane do biblioteki DLL, można zastosować aktualizację bez konieczności kompilowania lub zainstalowania całego programu ponownie.

Na poniższej liście opisano niektóre pliki, które są implementowane jako biblioteki DLL w systemach operacyjnych Windows:

  • pliki formantów ActiveX (.ocx)

    Przykładem formantu ActiveX jest formant kalendarza, który pozwala wybrać datę z kalendarza.

  • Pliki w Panelu sterowania (.cpl)

    Przykładem pliku .cpl jest element, który znajduje się w Panelu sterowania. Każdy element jest wyspecjalizowaną biblioteką DLL.

  • pliki sterownika urządzenia (.drv)

    Przykładem sterownika urządzenia jest sterownik drukarki, który steruje drukowaniem na drukarce.

DLL - zalety

Na poniższej liście opisano niektóre zalety, które są zapewnione, gdy program używa biblioteki DLL:

  • Mniejsze użycie zasobów

    Gdy wiele programów korzysta z tej samej biblioteki funkcji, biblioteka DLL może zmniejszyć duplikowanie kodu, który jest ładowany na dysku i w pamięci fizycznej. Może to mieć duży wpływ na wydajność nie tylko programu działającego na pierwszym planie, ale także innych programów działających w systemie operacyjnym Windows.

  • Promuje modułową architekturę

    Biblioteka DLL pomaga promować opracowywanie programów modułowych. Ułatwia ona opracowywanie dużych programów wymagających wielu wersji językowych lub programu wymagającego architektury modułowej. Przykładem programu modułowego jest program księgowości, posiadający wiele modułów, które mogą być ładowane dynamicznie w czasie wykonywania.

  • Ułatwia wdrażanie i instalację

    Gdy funkcja w bibliotece DLL wymaga aktualizacji lub poprawki, wdrażanie i instalacja biblioteki DLL nie wymaga ponownego połączenia programu z biblioteką DLL. Ponadto jeśli wiele programów korzysta z tej samej biblioteki DLL, programy te skorzystają z aktualizacji lub poprawki. Ten problem może występować częściej podczas korzystania z biblioteki DLL innej firmy, która jest regularnie aktualizowana lub poprawiana.

Zależności bibliotek DLL

Gdy program lub biblioteka DLL używa funkcji DLL w innej bibliotece DLL, powstaje zależność. Program nie jest już samodzielny, a program może napotkać problemy, jeśli zależność zostanie przerwana. Na przykład program może nie działać, jeśli wystąpi jedna z następujących czynności:

  • Zależna biblioteka DLL jest uaktualniana do nowej wersji.
  • Zależna biblioteka DLL jest naprawiana.
  • Zależna biblioteka DLL jest zastępowana wcześniejszą wersją.
  • Zależna biblioteka DLL jest usuwana z komputera.

Te czynności są nazywane konfliktami bibliotek DLL. Jeśli zgodność z poprzednimi wersjami nie jest wymuszana, program może nie zostać pomyślnie uruchomiony.

Na poniższej liście opisano zmiany wprowadzone w Windows 2000 i w kolejnych systemach operacyjnych Windows, aby zminimalizować problemy z zależnościami:

  • Ochrona plików systemu Windows

    W ochronie plików systemu Windows system operacyjny uniemożliwia aktualizację lub usunięcie przez nieautoryzowanego użytkownika bibliotek DLL systemu. Gdy instalacja programu próbuje usunąć lub zaktualizować bibliotekę DLL zdefiniowaną jako systemowa biblioteka DLL, ochrona plików systemu Windows będzie szukać prawidłowego podpisu cyfrowego.

  • Prywatne biblioteki DLL

    Prywatne biblioteki DLL umożliwiają wyodrębnienie programu ze zmian wprowadzonych w udostępnionych bibliotekach DLL. Prywatne biblioteki DLL używają informacji specyficznych dla wersji lub pustego pliku .local, aby wymusić wersję biblioteki DLL, która jest używana przez program. Aby korzystać z prywatnych bibliotek DLL, zlokalizuj biblioteki DLL w folderze głównym programu. Następnie w przypadku nowych programów należy dodać informacje specyficzne dla wersji do biblioteki DLL. W przypadku starych programów użyj pustego pliku .local. Każda metoda informuje system operacyjny, aby używać prywatnych bibliotek DLL, które znajdują się w folderze głównym programu.

Narzędzia do rozwiązywania problemów z biblioteką DLL

Dostępne są różne narzędzia ułatwiające rozwiązywanie problemów z biblioteką DLL. Oto niektóre z dostępnych narzędzi.

Dependency Walker

Narzędzie Dependency Walker umożliwia rekursywne skanowania dla wszystkich zależnych bibliotek DLL, które są używane przez program. Po otwarciu programu w Dependency Walker narzędzie Dependency Walker wykonuje następujące testy:

  • Dependency Walker sprawdza brakujące biblioteki DLL.
  • Dependency Walker sprawdza pliki programów lub bibliotek DLL, które nie są prawidłowe.
  • Dependency Walker sprawdza, czy funkcje importowania i eksportowania są zgodne.
  • Dependency Walker sprawdza cykliczne błędy zależności.
  • Dependency Walker sprawdza moduły, które nie są prawidłowe, ponieważ moduły te są przeznaczone dla innego systemu operacyjnego.

Za pomocą narzędzia Dependency Walker można dokumentować wszystkie biblioteki DLL, których używa program. Może to pomóc w zapobieganiu problemom z biblioteką DLL, które mogą wystąpić w przyszłości i ich rozwiązywaniu. Dependency Walker znajduje się w następującym katalogu podczas instalacji Visual Studio 6.0:

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

DLL Universal Problem Solver

Narzędzie DLL Universal Problem Solver (DUPS) służy do inspekcji, porównywania, dokumentowania i wyświetlania informacji o bibliotece DLL. Poniższa lista zawiera opis narzędzi, które tworzą narzędzie DUPS:

  • Dlister.exe

    To narzędzie wylicza wszystkie biblioteki DLL na komputerze i rejestruje informacje w pliku tekstowym lub pliku bazy danych.

  • Dcomp.exe

    To narzędzie porównuje biblioteki DLL, które są wymienione w dwóch plikach tekstowych i tworzy trzeci plik tekstowy, który zawiera różnice.

  • Dtxt2DB.exe

    To narzędzie ładuje pliki tekstowe, które są tworzone przy użyciu narzędzia Dlister.exe i narzędzia Dcomp.exe do bazy danych dllHell.

  • DlgDtxt2DB.exe

    To narzędzie udostępnia graficzną wersję interfejsu użytkownika (GUI) narzędzia Dtxt2DB.exe.

Baza danych pomocy DLL

Baza danych pomocy biblioteki DLL pomaga zlokalizować określone wersje bibliotek DLL, które są instalowane przez produkty oprogramowania firmy Microsoft.

Tworzenie bibliotek DLL

W tej sekcji opisano problemy i wymagania, które należy wziąć pod uwagę podczas opracowywania własnych bibliotek DLL.

Typy bibliotek DLL

Podczas ładowania biblioteki DLL w aplikacji, dwie metody łączenia umożliwiają wywoływanie wyeksportowanych funkcji DLL. Dwie metody łączenia to dynamiczne łączenie w czasie wczytywania i dynamiczne łączenie w czasie wykonywania.

Dynamiczne łączenie w czasie wczytywania

W przypadku łączenia dynamicznego w czasie wczytywania aplikacja jawnie wywołuje wyeksportowane funkcje biblioteki DLL, takie jak funkcje lokalne. Aby użyć dynamicznego łączenia w czasie wczytywania, podaj plik nagłówka (.h) i plik biblioteki importu (.lib) podczas kompilowania i łączenia aplikacji. W takim przypadku konsolidator udostępni systemowi informacje wymagane do załadowania biblioteki DLL i rozpoznania wyeksportowanych lokalizacji funkcji biblioteki DLL w czasie wczytywania.

Dynamiczne łączenie w czasie wykonywania

W przypadku dynamicznego łączenia w czasie wykonywania aplikacja wywołuje funkcję LoadLibrary lub funkcję LoadLibraryEx w celu załadowania biblioteki DLL w czasie wykonywania. Po pomyślnym załadowaniu biblioteki DLL użyj funkcji GetProcAddress, aby uzyskać adres wyeksportowanej funkcji DLL, którą chcesz wywołać. W przypadku korzystania z dynamicznego łączenia w czasie wykonywania nie jest potrzebny plik biblioteki importu.

Poniższa lista zawiera opis kryteriów aplikacji, według których należy używać dynamicznego łączenia w czasie ładowania i dynamicznego łączenia w czasie wykonywania:

  • Wydajność uruchamiania

    Jeśli początkowa wydajność uruchamiania aplikacji jest ważna, należy użyć dynamicznego łączenia w czasie wykonywania.

  • Łatwość użycia

    W przypadku łączenia dynamicznego w czasie ładowania wyeksportowane funkcje biblioteki DLL są podobne do funkcji lokalnych. Dzięki temu można łatwo wywołać te funkcje.

  • Logika aplikacji

    W trakcie dynamiczne łączenie w czasie wykonywania aplikacja może rozgałęzić się, aby załadować różne moduły zgodnie z wymaganiami. Ważne jest, aby opracowywać wersje w wielu językach.

Punkt wejścia biblioteki DLL

Podczas tworzenia biblioteki DLL można opcjonalnie określić funkcję punktu wejścia. Funkcja punktu wejścia jest wywoływana, gdy procesy lub wątki dołączają się do biblioteki DLL lub odłączają się od biblioteki DLL. Funkcja punktu wejścia umożliwia inicjowanie struktur danych lub niszczenie struktur danych zgodnie z wymaganiami biblioteki DLL. Ponadto jeśli aplikacja jest wielowątkowa, można użyć lokalnego magazynu wątków (TLS) do przydzielenia pamięci, który jest prywatny dla każdego wątku w funkcji punktu wejścia. Poniższy kod jest przykładem funkcji punktu wejścia 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;
}

Gdy funkcja punktu wejścia zwraca wartość FAŁSZ, aplikacja nie uruchomi się, jeśli używasz dynamicznego łączenia w czasie ładowania. Jeśli używasz dynamicznego łączenia w czasie wykonywania, tylko poszczególne biblioteki DLL nie zostaną załadowane.

Funkcja punktu wejścia powinna wykonywać tylko proste zadania inicjowania i nie należy wywoływać innych funkcji ładowania lub kończenia biblioteki DLL. Na przykład w funkcji punktu wejścia nie należy bezpośrednio ani pośrednio wywoływać funkcji LoadLibrary ani funkcji LoadLibraryEx. Ponadto nie należy wywoływać funkcji FreeLibrary po zakończeniu procesu.

Uwaga 16.

W aplikacjach wielowątkowych upewnij się, że dostęp do danych globalnych biblioteki DLL jest synchronizowany (bezpieczny wątek), aby uniknąć ewentualnego uszkodzenia danych. Aby to zrobić, użyj protokołu TLS do dostarczania unikatowych danych dla każdego wątku.

Eksportowanie funkcji biblioteki DLL

Aby wyeksportować funkcje DLL, można dodać słowo kluczowe funkcji do wyeksportowanych funkcji DLL lub utworzyć plik definicji (.def) modułu, który zawiera listę wyeksportowanych funkcji DLL.

Aby użyć słowa kluczowego funkcji, należy zadeklarować każdą funkcję, którą chcesz wyeksportować, za pomocą następującego słowa kluczowego:
__declspec(dllexport)

Aby używać wyeksportowanych funkcji biblioteki DLL w aplikacji, należy zadeklarować każdą funkcję, którą chcesz zaimportować przy użyciu następującego słowa kluczowego: __declspec(dllimport)

Zazwyczaj należy użyć jednego pliku nagłówka, który ma instrukcję define i instrukcję ifdef, aby oddzielić instrukcję eksportu i instrukcję import.

Można również użyć pliku definicji modułu do deklarowania wyeksportowanych funkcji DLL. W przypadku korzystania z pliku definicji modułu, nie trzeba dodawać słowa kluczowego funkcji do wyeksportowanych funkcji DLL. W pliku definicji modułu deklarujesz instrukcję LIBRARY i instrukcję EXPORTS dla biblioteki DLL. Poniższy kod jest przykładem pliku definicji.

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

Przykładowa biblioteka DLL i aplikacja

W programie Visual C++ 6.0 możesz utworzyć bibliotekę DLL, wybierając typ projektu Win32 Dynamic-Link Library lub typ projektu MFC AppWizard (dll).

Poniższy kod jest przykładem biblioteki DLL utworzonej w języku Visual C++ przy użyciu typu projektu 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

Poniższy kod jest przykładem projektu Win32 Application, który wywołuje funkcję wyeksportowanej biblioteki DLL w pliku DLL SampleDLL.

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

Uwaga 16.

W przypadku łączenia dynamicznego w czasie ładowania należy połączyć bibliotekę importu SampleDLL.lib utworzoną podczas tworzenia projektu SampleDLL.

W trakcie dynamicznego łączenia w czasie wykonywania, użyj kodu, który jest podobny do następującego kodu do wywoływania SampleDLL.dll wyeksportowanej funkcji 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);
}
...

Podczas kompilowania i łączenia aplikacji SampleDLL, system operacyjny Windows wyszukuje SampleDLL DLL w następujących lokalizacjach w następującej kolejności:

  1. Folder aplikacji

  2. Bieżący folder

  3. Folder systemu Windows

    Uwaga 16.

    Funkcja GetSystemDirectory zwraca ścieżkę folderu systemu Windows.

  4. Folder systemu Windows

    Uwaga 16.

    Funkcja GetWindowsDirectory zwraca ścieżkę folderu systemu Windows.

Środowisko .NET Framework

Wraz z wprowadzeniem środowisk .NET i .NET Framework większość problemów związanych z bibliotekami DLL została wyeliminowana przy użyciu środowisk. Zestaw jest logiczną jednostką funkcjonalności, która działa pod kontrolą środowiska uruchomieniowego języka wspólnego (CLR) .NET. Zestaw fizycznie istnieje jako plik .dll lub jako plik .exe. Jednak wewnętrznie zestaw różni się od biblioteki DLL Microsoft Win32.

Plik zestawu zawiera manifest zestawu, metadane typu, kod języka pośredniego (MSIL) Microsoft i inne zasoby. Manifest zestawu zawiera metadane zestawu, który zaś zawiera wszystkie informacje, które są wymagane do tego, aby zestaw samodzielnie się opisywał. W manifeście zestawu znajdują się następujące informacje:

  • Nazwa zestawu
  • Wersja
  • Informacje o kulturze
  • Informacje o silnej nazwie
  • Lista plików zestawu
  • Informacje referencyjne o typie
  • Informacje dotyczące zależności i odwołań zestawu

Nie można bezpośrednio wykonać kodu MSIL zawartego w zestawie. Zamiast tego wykonywanie kodu MSIL jest zarządzane za pomocą CLR. Domyślnie podczas tworzenia zestawu, zestaw jest prywatny dla aplikacji. Utworzenie zestawu udostępnionego wymaga przypisania silnej nazwy do zestawu, a następnie opublikowania wirtualnego pliku dziennika w globalnej pamięci podręcznej zestawów.

Poniższa lista zawiera opis niektórych funkcji zestawów w porównaniu do funkcji bibliotek DLL systemu Win32:

  • Samodzielne opisywanie

    Podczas tworzenia zestawu, wszystkie informacje, które są wymagane dla środowiska CLR do uruchomienia zestawu są zawarte w manifeście zestawu. Manifest zestawu zawiera listę zależności zestawów. W związku z tym CLR może zachować spójny zbiór zestawów, które są używane w aplikacji. W bibliotekach DLL systemu Win32 nie można zachować spójności między zestawami bibliotek DLL, które są używane w aplikacji, korzystając z udostępnionych bibliotek DLL.

  • Wersje

    W manifeście zestawu informacje o wersji są rejestrowane i wymuszane przez środowisko CLR. Ponadto zasady wersji umożliwiają wymuszenie użycia specyficzne dla wersji. W przypadku bibliotek DLL Win32 nie można wymusić obsługi wersji przez system operacyjny. Musisz upewnić się, że biblioteki DLL są zgodne z poprzednimi wersjami.

  • Instalacje w trybie równoległym

    Zestawy obsługują instalacje w trybie równoległym. Jedna aplikacja może używać jednej wersji zestawu, a druga może używać innej wersji zestawu. Począwszy od systemu Windows 2000, instalacje w trybie równoległym są obsługiwane przez lokalizowanie bibliotek DLL w folderze aplikacji. Ponadto Ochrona plików systemu Windows zapobiega nadpisaniu lub zastąpieniu przez nieautoryzowanego użytkownika bibliotek DLL systemu.

  • Samodzielne oddzielenie i izolacja

    Aplikacja opracowana przy użyciu zestawu może być niezależna i odizolowana od innych aplikacji uruchomionych na komputerze. Ta funkcja pomaga w tworzeniu instalacji o zerowym wpływie na środowisko pracy.

  • Wykonanie

    Zestaw jest uruchamiany w ramach uprawnień zabezpieczeń, które są dostarczane w manifeście zestawu i które są kontrolowane przez środowisko CLR.

  • Niezależny od języka

    Zestaw można opracować przy użyciu jednego z obsługiwanych języków .NET. Na przykład można utworzyć zestaw w programie Microsoft Visual C#, a następnie użyć zestawu w projekcie Visual Basic .NET.

Zbieranie danych

Jeśli potrzebujesz pomocy ze strony pomocy technicznej firmy Microsoft, zalecamy zebranie informacji, wykonując kroki wymienione w artykule Zbieranie informacji przy użyciu zestawu narzędzi TSS w przypadku problemów związanych z wdrożeniem.

Informacje