Delphi DllMain DLL_PROCESS_DETACH在DLL_PROCESS_ATTACH之前被调用

9

我遇到了很多麻烦来处理我在Delphi中编写的DLL。我已经在库中使用以下代码设置了一个DllMain函数:

begin
  DllProc := DllMain;
end.

我的 `DllMain` 过程如下所示:
procedure DllMain(reason: Integer);
begin
  if reason = DLL_PROCESS_DETACH then
    OutputDebugString('DLL PROCESS DETACH')
  else if reason = DLL_PROCESS_ATTACH then
    OutputDebugString('DLL PROCESS ATTACH')
  else if reason = DLL_THREAD_ATTACH then
    OutputDebugString('DLL THREAD ATTACH')
  else if reason = DLL_THREAD_DETACH then
    OutputDebugString('DLL THREAD DETACH')
  else
    OutputDebugString('DllMain');
end;

我发现DETACH似乎被一个我无法控制的调用者(可能是两次?!)在ATTACH之前调用。这是否可能,或者我对它的工作方式有误解?我的期望是每个ATTACH调用都应该有一个匹配的DETACH调用,但情况似乎并非如此。
这里发生了什么事情?!
2个回答

14

不幸的是,当你的dll代码中执行begin时,操作系统已经调用了你的库中的DllMain函数。因此,当你的DllProc := DllMain;语句执行时,已经为时过晚了。Delphi编译器不允许用户代码在dll连接到进程时执行。建议的解决方法(如果可以称之为解决方法)是在单元初始化部分或库代码中自己调用DllMain函数:

begin
  DllProc := DllMain;
  DllMain(DLL_PROCESS_ATTACH);
end;

相关文档资料如下:

注意: 只有当 DLL 的初始化代码调用该过程并将 DLL_PROCESS_ATTACH 指定为参数时,才会将 DLL_PROCESS_ATTACH 传递给该过程。


哦...我原本希望这个会是解决我所有问题的方案,但这些额外的知识(虽然正确并回答了我的问题),似乎还没有解决我的问题。看起来我得再发一个问题 : )。感谢你的帮助! - aardvarkk
你不理解什么呢?所有的内容都在这个问题里。在你的代码可以执行之前,唯一发生的DllMain调用是DLL_PROCESS_ATTACH。所以你只需要按照Sertac的方式编写它,就没有问题了。 - David Heffernan
不,这非常清楚。我理解并可以实现它。然而,它揭示了一个事实,即我的更大问题的答案(我希望与此相关),实际上与这个问题无关。因此搜索继续! - aardvarkk

-1
我发现的是,在ATTACH被调用之前,DETACH似乎被一个(我无法控制的)调用者调用了两次?根据Petzold的《Programming Windows 5th edition》所述,当应用程序启动时会调用DLL_PROCESS_ATTACH,当已连接应用程序内部启动新线程时会调用DLL_THREAD_ATTACH。当附加到您的应用程序的应用程序退出时,将调用DLL_PROCESS_DETACH。当已连接应用程序中的线程退出时,将调用DLL_THREAD_DETACH。请注意,可能会在没有相应的DLL_THREAD_ATTACH的情况下调用DLL_THREAD_DETACH。这发生在线程在应用程序链接到dll之前启动时。这主要发生在应用程序使用LoadLibrary手动加载dll而不是在编译时静态链接的情况下。

我不明白。你是指没有进程的线程吗?而且 'LoadLibrary' 不会导致 'DLL_PROCESS_ATTACH' 吗? - Sertac Akyuz
这似乎没有解释为什么 DLL_PROCESS_DETACH 会发生多次。 - nobody

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接