1、首先写个简单的DLL,用来验证
BOOL APIENTRY DllMain( HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved ) { switch (ul_reason_for_call) { case DLL_PROCESS_ATTACH: { printf("DLL_PROCESS_ATTACH\n"); } break; case DLL_PROCESS_DETACH: { printf("DLL_PROCESS_DETACH\n"); } break; case DLL_THREAD_ATTACH: { printf("DLL_THREAD_ATTACH\n"); } break; case DLL_THREAD_DETACH: { printf("DLL_THREAD_DETACH\n"); } break; } return TRUE; }
2、再写一个测试用的EXE:
unsigned int __stdcall ThreadFun(PVOID pM); //int WinMain(HINSTANCE hInstance, // HINSTANCE hPrevInstance, // LPSTR lpCmdLine, // int nCmdShow) void main() { HMODULE hMod = LoadLibrary("TestDLL.dll"); HANDLE hThread = (HANDLE)_beginthreadex(NULL, 0, ThreadFun, NULL, 0, NULL); if(!hThread) { return; } WaitForSingleObject(hThread, INFINITE); FreeLibrary(hMod); getchar(); exit(0); // return 0; } unsigned int __stdcall ThreadFun(PVOID pM) { printf("线程ID号为%4d的子线程说:Hello World\n", GetCurrentThreadId()); return 0; }
3、你把这个EXE跑一遍就会发现,在线程被创建的时候,也会执行一次已经被加载的DLL的DLLMain,加载原因是DLL_THREAD_ATTACH,离开时也同理,最终显示结果如下:
4、如果你在原先的DLL代码中加入DisableThreadLibraryCalls调用,那么就不会在线程启动时去执行这个DLL的DLLMain了:
当然这里关于线程是否执行DLLMain的DLL_THREAD_ATTACH和DLL_THREAD_DETACH的,还有一些比较细节的逻辑,可以参考: