HOWTO: 如何提供一个 MFC Regular DLL 中自己 DllMain
<script type="text/javascript">function loadTOCNode(){}</script>
注意:这篇文章是由无人工介入的自动的机器翻译系统翻译完成。这些文章是微软为不懂英语的用户提供的, 以使他们能够理解这些文章的内容。微软不保证机器翻译的正确度,也不对由于内容的误译或者客户对它的使用所引起的任何直接的, 或间接的可能的问题负责。
文章编号 | : | 148791 |
最后修改 | : | 2006年11月21日 |
修订 | : | 2.1 |
概要
<script type="text/javascript">loadTOCNode(1, 'summary');</script>
默认设计, MFC Regular DLL 具有由 MFC 自动提供默认 DllMain 函数。 常规 DLL 应不提供自己的 DllMain。 应在一个 - CWinApp 派生类常规 DLL 中的 InitInstance 成员函数完成该 DLL 被加载时需要任何初始化。 deinitialization 和终止代码应转 ExitInstance 成员函数中。
当进程 (DLL_PROCESS_ATTACH) 附加到 DLL, 只有当进程分离 (DLL_PROCESS_DETACH) 从 DLL 称为 ExitInstance 由 MFC DllMain 但是, 是只调用 InitInstance。 如果是需要处理到线程附件并从 (DLL_THREAD_ATTACH 和 DLL_THREAD_DETACH) detachment MFC Regular DLL, 中 Regular DLL 将需要提供自己的 DllMain。 本文介绍如何执行它。
当进程 (DLL_PROCESS_ATTACH) 附加到 DLL, 只有当进程分离 (DLL_PROCESS_DETACH) 从 DLL 称为 ExitInstance 由 MFC DllMain 但是, 是只调用 InitInstance。 如果是需要处理到线程附件并从 (DLL_THREAD_ATTACH 和 DLL_THREAD_DETACH) detachment MFC Regular DLL, 中 Regular DLL 将需要提供自己的 DllMain。 本文介绍如何执行它。
更多信息
<script type="text/javascript">loadTOCNode(1, 'moreinformation');</script>
创建常规 DLL, 时 MFC 源强制链接对于源文件 /Msdev/Mfc/Src/Dllmodul.cpp 代码中。 Dllmodul.cpp 包含大部分的代码添加到常规 DLL 以支持 MFC DLL 中。 Dllmodul.cpp 中最重要功能之一是 DllMain 函数。
代码添至 MFC DllMain, 将 /Msdev/Mfc/Src/Dllmodul.cpp 源文件复制到项目目录, 并项目中包含副本。 这份 Dllmodul.cpp 编译并链接到 DLL 代替 Dllmodul.cpp, Mfc/Src 目录中, 更改 DllMain 中将显示最后 DLL 中。
主 caveat 是, 这是不推荐解决方案而绝对必要时应该只使用。 对 Dllmodul.cpp 中代码的任何更改将 undoubtedly 具有非预期结果。 添加代码只, 不要删除或修改现有代码。
对于常规 DLL 使用 MFC 共享 Lib, 中的模块状态应设置处添加代码, 从 DllMain 返回之前还原。 有关示例是处理 DLL_THREAD_ATTACH 和 DLL_THREAD_DETACH 通知并正确切换模块状态尽量 DllMain 指向本文中示例代码。
附加依赖 DllMain 和 DLL_THREAD_ATTACH DLL_THREAD_DETACH 调用因下列条件时必须小心:
备注: MFC CWnd 对象、 CDC 对象、 CMenu 对象、 GDI 对象, 和 CImageList 对象是限于基于线程, 每个模块基础。 换句话说, 一个模块或线程中创建 MFC 对象无法传递到和/或不同模块或线程中使用。 这有特殊关联的任何代码添加到处理 DllMain 中 DLL_THREAD_DETACH DLL_THREAD_ATTACH 或者因为出于这些原因以不同的称为 DllMain。 期间 DLL_PROCESS_ATTACH DllMain 或 InitInstance 中创建 CWnd 对象, 例如, 期间 DLL_THREAD_ATTACH 无法有效。
代码添至 MFC DllMain, 将 /Msdev/Mfc/Src/Dllmodul.cpp 源文件复制到项目目录, 并项目中包含副本。 这份 Dllmodul.cpp 编译并链接到 DLL 代替 Dllmodul.cpp, Mfc/Src 目录中, 更改 DllMain 中将显示最后 DLL 中。
主 caveat 是, 这是不推荐解决方案而绝对必要时应该只使用。 对 Dllmodul.cpp 中代码的任何更改将 undoubtedly 具有非预期结果。 添加代码只, 不要删除或修改现有代码。
对于常规 DLL 使用 MFC 共享 Lib, 中的模块状态应设置处添加代码, 从 DllMain 返回之前还原。 有关示例是处理 DLL_THREAD_ATTACH 和 DLL_THREAD_DETACH 通知并正确切换模块状态尽量 DllMain 指向本文中示例代码。
附加依赖 DllMain 和 DLL_THREAD_ATTACH DLL_THREAD_DETACH 调用因下列条件时必须小心:
• | 使用值 DLL_THREAD_ATTACH 进程, 中创建一个线程时系统调用 DllMain 对于每个 DLL 插入映射到进程。 对于任何现有线程但是, 如果进程有中新 DLL 是映射到它, 时运行多个线程 DllMain 不调用带有 DLL_THREAD_ATTACH 值。 |
• | 不使用值 DLL_THREAD_ATTACH 进程的主线程调用 DllMain。 |
• | 对于除非通过调用 ExitThread 线程终止每个 DLL DllMain 不调用以对任何线程线程终止 (通过调用到 ExitThread,) 上使用 DLL_THREAD_DETACH 值调用 DllMain。 |
• | 如果线程终止由于到呼叫到 TerminateThread, DllMain 不调用带有 DLL_THREAD_DETACH 值。 |
• | 很可能为进程以调用 LoadLibrary 来加载 DLL 以, 导致调用以 DllMain, 然后线程终止, 上导致调用以 dllMain 以没有以往调用 DLL_THREAD_ATTACH 中线程。 因此最好调用 LoadLibrary 线程也调用 FreeLibrary。 |
示例代码
<script type="text/javascript">loadTOCNode(2, 'moreinformation');</script>
// export DllMain for the DLL
// Add code in the specified sections only.
// Remove code at your own risk.
extern "C"
BOOL WINAPI DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID
/*lpReserved*/)
{
if (dwReason == DLL_PROCESS_ATTACH)
{
// ... Code abbreviated from DLLMODUL.CPP
}
else if (dwReason == DLL_PROCESS_DETACH)
{
// ... Code abbreviated from DLLMODUL.CPP
}
// NEW CODE ADDED HERE
// -------------------
else if (dwReason == DLL_THREAD_ATTACH)
{
#ifdef _AFXDLL
// set module state
ASSERT(AfxGetThreadState()->m_pPrevModuleState == NULL);
AfxGetThreadState()->m_pPrevModuleState =
AfxSetModuleState(AfxGetStaticModuleState());
#endif
// ADD DLL_THREAD_ATTACH CODE HERE
// Remember that this won't necessarily be called for
// every thread in the process into which this DLL is mapped
// Threads created by the process BEFORE the DLL
// was loaded will not call into DLL_THREAD_ATTACH.
#ifdef _AFXDLL
// restore previously-saved module state
VERIFY(AfxSetModuleState(AfxGetThreadState()->m_pPrevModuleState)
== AfxGetStaticModuleState());
DEBUG_ONLY(AfxGetThreadState()->m_pPrevModuleState = NULL);
#endif
}
else if (dwReason ==DLL_THREAD_DETACH)
{
#ifdef _AFXDLL
// set module state
ASSERT(AfxGetThreadState()->m_pPrevModuleState == NULL);
AfxGetThreadState()->m_pPrevModuleState =
AfxSetModuleState(AfxGetStaticModuleState());
#endif
// ADD DLL_THREAD_DETACH CODE HERE
#ifdef _AFXDLL
// restore previously-saved module state
VERIFY(AfxSetModuleState(AfxGetThreadState()->m_pPrevModuleState)
== AfxGetStaticModuleState());
DEBUG_ONLY(AfxGetThreadState()->m_pPrevModuleState = NULL);
#endif
}
return TRUE;
}