Kommentar
Åtkomst till den här sidan kräver auktorisering. Du kan prova att logga in eller ändra kataloger.
Åtkomst till den här sidan kräver auktorisering. Du kan prova att ändra kataloger.
En valfri startpunkt i ett DLL-bibliotek (Dynamic Link Library). När systemet startar eller avslutar en process eller tråd anropas startpunktsfunktionen för varje inläst DLL med hjälp av den första tråden i processen. Systemet anropar också startpunktsfunktionen för en DLL när den läses in eller tas bort med hjälp av funktionerna LoadLibrary och FreeLibrary .
Varning
Det finns betydande gränser för vad du kan göra på ett säkert sätt i en DLL-startpunkt. Se Allmänna metodtips för specifika Windows API:er som är osäkra att anropa i DllMain. Om du behöver något annat än den enklaste initieringen gör du det i en initieringsfunktion för DLL-filen. Du kan kräva att program anropar initieringsfunktionen när DllMain har körts och innan de anropar andra funktioner i DLL:en.
Exempel
BOOL WINAPI DllMain(
HINSTANCE hinstDLL, // handle to DLL module
DWORD fdwReason, // reason for calling function
LPVOID lpvReserved ) // reserved
{
// Perform actions based on the reason for calling.
switch( fdwReason )
{
case DLL_PROCESS_ATTACH:
// Initialize once for each new process.
// Return FALSE to fail DLL load.
break;
case DLL_THREAD_ATTACH:
// Do thread-specific initialization.
break;
case DLL_THREAD_DETACH:
// Do thread-specific cleanup.
break;
case DLL_PROCESS_DETACH:
if (lpvReserved != nullptr)
{
break; // do not do cleanup if process termination scenario
}
// Perform any necessary cleanup.
break;
}
return TRUE; // Successful DLL_PROCESS_ATTACH.
}
Det här är ett exempel från funktionenDynamic-Link Library Entry-Point.
Syntax
BOOL WINAPI DllMain(
_In_ HINSTANCE hinstDLL,
_In_ DWORD fdwReason,
_In_ LPVOID lpvReserved
);
Parameters
-
hinstDLL [in]
-
Ett handtag till DLL-modulen. Värdet är basadressen för DLL:en. HINSTANCE för en DLL är samma som HMODULE för DLL, så hinstDLL kan användas i anrop till funktioner som kräver en modulreferens.
-
fdwReason [in]
-
Orsakskoden som anger varför DLL-startpunktsfunktionen anropas. Den här parametern kan vara ett av följande värden.
Value Innebörd - DLL_PROCESS_ATTACH
- 1
DLL-filen läses in i det virtuella adressutrymmet för den aktuella processen som ett resultat av att processen startas eller som ett resultat av ett anrop till LoadLibrary. DLL:er kan använda den här möjligheten för att initiera instansdata eller använda funktionen TlsAlloc för att allokera ett TLS-index (Thread Local Storage).
Parametern lpvReserved anger om DLL:en läses in statiskt eller dynamiskt.- DLL_PROCESS_DETACH
- 0
DLL:en tas bort från det virtuella adressutrymmet i anropsprocessen eftersom den inte lästes in utan framgång eller referensantalet har nått noll (processerna har antingen avslutats eller anropat FreeLibrary en gång för varje gång det kallas LoadLibrary).
Parametern lpvReserved anger om DLL:en tas bort till följd av ett FreeLibrary-anrop , ett fel vid inläsning eller processavslutning.
DLL kan använda den här möjligheten för att anropa funktionen TlsFree för att frigöra alla TLS-index som allokerats med hjälp av TlsAlloc och frigöra alla trådlokala data.
Observera att tråden som tar emot DLL_PROCESS_DETACH-meddelandet inte nödvändigtvis är samma tråd som tog emot DLL_PROCESS_ATTACH-meddelandet .- DLL_THREAD_ATTACH
- 2
Den aktuella processen skapar en ny tråd. När detta inträffar anropar systemet startpunktsfunktionen för alla DLL:er som för närvarande är kopplade till processen. Anropet görs i kontexten för den nya tråden. DLL:er kan använda den här möjligheten för att initiera ett TLS-fack för tråden. En tråd som anropar funktionen DLL-startpunkt med DLL_PROCESS_ATTACH anropar inte funktionen DLL-startpunkt med DLL_THREAD_ATTACH.
Observera att en DLL-startpunktsfunktion anropas med det här värdet endast av trådar som skapats efter att DLL-filen har lästs in av processen. När en DLL läses in med LoadLibrary anropar befintliga trådar inte startpunktsfunktionen för den nyligen inlästa DLL:en.- DLL_THREAD_DETACH
- 3
En tråd avslutas rent. Om DLL:en har lagrat en pekare för allokerat minne i ett TLS-fack bör den använda den här möjligheten för att frigöra minnet. Systemet anropar startpunktsfunktionen för alla för närvarande inlästa DLL:er med det här värdet. Anropet görs i kontexten för den avslutande tråden. -
lpvReserved [in]
-
Om fdwReasonär DLL_PROCESS_ATTACH är lpvReservedNULL för dynamiska belastningar och icke-NULL för statiska belastningar.
Om fdwReasonär DLL_PROCESS_DETACH är lpvReservedNULL om FreeLibrary har anropats eller DLL-belastningen misslyckades och icke-NULL om processen avslutas.
Returvärde
När systemet anropar funktionen DllMain med värdet DLL_PROCESS_ATTACH returnerar funktionen TRUE om den lyckas eller FALSE om initieringen misslyckas. Om returvärdet är FALSE när DllMain anropas eftersom processen använder funktionen LoadLibraryreturnerar LoadLibrary NULL. (Systemet anropar omedelbart startpunktsfunktionen med DLL_PROCESS_DETACH och tar bort DLL:en.) Om returvärdet är FALSE när DllMain anropas under processens initiering avslutas processen med ett fel. Om du vill få utökad felinformation anropar du GetLastError.
När systemet anropar funktionen DllMain med något annat värde än DLL_PROCESS_ATTACH ignoreras returvärdet.
Remarks
DllMain är en platshållare för det biblioteksdefinierade funktionsnamnet. Du måste ange det faktiska namn som du använder när du skapar din DLL. Mer information finns i dokumentationen som ingår i dina utvecklingsverktyg.
Under den inledande processens start eller efter ett anrop till LoadLibrary söker systemet igenom listan över inlästa DLL:er för processen. För varje DLL som inte redan har anropats med värdet DLL_PROCESS_ATTACH anropar systemet DLL:ens startpunktsfunktion. Det här anropet görs i kontexten för tråden som gjorde att processadressutrymmet ändrades, till exempel den primära tråden i processen eller tråden som kallade LoadLibrary. Åtkomsten till startpunkten serialiseras av systemet på processomfattande basis. Trådar i DllMain håller lastarlåset så att inga ytterligare DLL:er kan läsas in eller initieras dynamiskt.
Om DLL:ens startpunktsfunktion returnerar FALSE efter ett DLL_PROCESS_ATTACH meddelande, får den ett DLL_PROCESS_DETACH-meddelande och DLL:en tas bort omedelbart. Men om DLL_PROCESS_ATTACH kod utlöser ett undantag får inte startpunktsfunktionen DLL_PROCESS_DETACH-meddelandet .
Det finns fall där startpunktsfunktionen anropas för en avslutande tråd även om startpunktsfunktionen aldrig anropades med DLL_THREAD_ATTACH för tråden:
- Tråden var den första tråden i processen, så systemet kallade startpunktsfunktionen med DLL_PROCESS_ATTACH-värdet .
- Tråden kördes redan när ett anrop till funktionen LoadLibrary gjordes, så systemet anropade aldrig startpunktsfunktionen för den.
När en DLL tas bort från en process till följd av en misslyckad belastning av DLL:en, processens avslutning eller ett anrop till FreeLibrary, anropar systemet inte DLL:ens startpunktsfunktion med DLL_THREAD_DETACH värde för processens enskilda trådar. DLL-filen skickas endast ett DLL_PROCESS_DETACH meddelande. DLL:er kan ta tillfället i akt att rensa alla resurser för alla trådar som är kända för DLL:et.
När du hanterar DLL_PROCESS_DETACH bör en DLL frigöra resurser, till exempel heapminne, endast om DLL:en tas bort dynamiskt (parametern lpvReserved är NULL). Om processen avslutas (parametern lpvReserved är icke-NULL) har alla trådar i processen förutom den aktuella tråden antingen redan avslutats eller uttryckligen avslutats av ett anrop till funktionen ExitProcess , vilket kan lämna vissa processresurser, till exempel heaps i ett inkonsekvent tillstånd. I det här fallet är det inte säkert för DLL-filen att rensa resurserna. I stället bör DLL:en tillåta att operativsystemet återtar minnet.
Om du avslutar en process genom att anropa TerminateProcess eller TerminateJobObject får inte DLL:erna för den processen DLL_PROCESS_DETACH meddelanden. Om du avslutar en tråd genom att anropa TerminateThread får inte DLL:er för den tråden DLL_THREAD_DETACH meddelanden.
Startpunktsfunktionen bör endast utföra enkla initierings- eller avslutningsuppgifter. Den får inte anropa funktionen LoadLibrary eller LoadLibraryEx (eller en funktion som anropar dessa funktioner), eftersom detta kan skapa beroendeloopar i DLL-inläsningsordningen. Detta kan resultera i att en DLL används innan systemet har kört sin initieringskod. På samma sätt får startpunktsfunktionen inte anropa funktionen FreeLibrary (eller en funktion som anropar FreeLibrary) under processens avslutning, eftersom detta kan leda till att en DLL används när systemet har kört sin avslutningskod.
Eftersom Kernel32.dll garanterat läses in i processadressutrymmet när startpunktsfunktionen anropas resulterar anropande funktioner i Kernel32.dll inte att DLL:en används innan dess initieringskod har körts. Därför kan startpunktsfunktionen anropa funktioner i Kernel32.dll som inte läser in andra DLL:er. DllMain kan till exempel skapa synkroniseringsobjekt som kritiska avsnitt och mutexar och använda TLS. Tyvärr finns det inte en omfattande lista över säkra funktioner i Kernel32.dll.
Anropa funktioner som kräver andra DLL:er än Kernel32.dll kan leda till problem som är svåra att diagnostisera. Om du till exempel anropar funktionerna User, Shell och COM kan det orsaka fel om åtkomstöverträdelser, eftersom vissa funktioner läser in andra systemkomponenter. Omvänt kan anrop av funktioner som dessa under avslutningen orsaka fel vid åtkomstöverträdelser eftersom motsvarande komponent kanske redan har tagits bort eller inte har initierats.
Eftersom DLL-meddelanden serialiseras bör startpunktsfunktioner inte försöka kommunicera med andra trådar eller processer. Dödlägen kan uppstå till följd av detta.
Information om metodtips när du skriver en DLL finns i Metodtips för dynamiskt länkbibliotek.
Om din DLL är länkad till C-körningsbiblioteket (CRT) anropar startpunkten som tillhandahålls av CRT konstruktorerna och destruktorerna för globala och statiska C++-objekt. Dessa begränsningar för DllMain gäller därför även för konstruktorer och destruktörer och all kod som anropas från dem.
Överväg att anropa DisableThreadLibraryCalls när du tar emot DLL_PROCESS_ATTACH, såvida inte din DLL är länkad till det statiska C-körningsbiblioteket (CRT).
Requirements
| Krav | Value |
|---|---|
| Lägsta klient som stöds |
Windows XP [endast skrivbordsappar] |
| Lägsta server som stöds |
Windows Server 2003 [endast skrivbordsappar] |
| Header |
|