我的问题与this one不完全相同(这不是理论上的,只有没有消息循环的主线程,InitInstance和ExitInstance都没有适合的调用)。
我正在使用没有消息循环的控制台应用程序;这个应用程序使用LoadLibrary函数加载一个exe,以便它可以使用其导出的函数。坏消息:没有调用exe的DllMain函数(我验证了符号表,使用def文件,DllMain正确显示); the doc says如果加载的模块是DLL(太糟糕),则调用它。
调用LoadLibrary时可能会导致exe的DllMain函数执行的条件(如果存在)有什么条件(可能再次调用FreeLibrary时)?
祝你好运
答案 0 :(得分:4)
最明显的条件是调用LoadLibrary()的进程显式获取GetProcAddress(“DllMain”)然后调用它。
答案 1 :(得分:3)
条件是:
1)正在加载的二进制文件被编译为DLL(当使用gcc / ld时它表示使用--shared
选项;如果使用--shared
,则生成的文件将是一个dll,并且不会运行,请参阅下文)
2)IMAGE_FILE_DLL
在正在加载的二进制文件的PE文件头中设置。如果已设置,则file为dll,并且Windows链接器在将此文件链接到您的程序时将为您调用其DllMain()
函数(无论它如何链接 - LoadLibrary()
在运行时或{ {1}}在编译时)。为此,文件也必须满足(1)。但是使用此标志,正在加载的二进制文件将无法运行。如果未设置-llibraryname
,则在将文件加载到您的程序时,将不会调用IMAGE_FILE_DLL
。
使用DllMain()
编译dll,然后从其标题中手动删除--shared
(即使用十六进制编辑器)将无效 - 当您运行它时,只会执行IMAGE_FILE_DLL
,并且DllMain()
将是一个未定义的数字(我的机器上为fdwReason
)。
<强>更新强>
Windows上的所有DLL和EXE文件都是PE文件,区别在于它们的链接方式以及标题中设置的标志。这就是为什么我写0x28ffd4
,而不是file being loaded
。
最后一段还描述了将文件编译为dll,然后通过弄乱其标题将其转换为exe的方案。它不起作用。
命名与它无关(您可以选择任何名称,并且通过一些dll being loaded
+ pexports
修补,您可以为.exe文件创建导入库,并能够将其链接为dlltool
澄清:
-lexenamewithoutextension
的情况下编译它:
--shared
将不会在其中设置,它将是可运行的,但在链接时不会调用DllMain()。IMAGE_FILE_DLL
进行编译:
--shared
将被设置在其中,它不会被运行,但是当你链接它时会调用DllMain()。IMAGE_FILE_DLL
的情况下编译它,那么手动打开它中的--shared
标志:
IMAGE_FILE_DLL
进行编译,请手动关闭其中的--shared
标记:
答案 2 :(得分:1)
Windows确实完全忽略了该函数的名称“DllMain”(Windows NT 3.x的旧Windows API文档明确说明了这一点。)
加载DLL时不是函数DllMain(),而是调用位于文件入口点的函数。
当然,链接器将以DllMain()为此函数的方式创建DLL文件。
但是对于EXE文件,入口函数(将调用WinMain())位于入口点。
因此很明显,当将EXE文件作为DLL加载时,Windows无法调用此函数。
答案 3 :(得分:0)
完成MSalters的好答案:
然后,在LoadLibrary之后使用DLL_XXX_ATTACH调用“假”DllMain,并在FreeLibrary之前调用DLL_XXX_DETACH,并手动调用其他调用。
下面的另一个实现是构建和加载一个接口DLL,它可以自动回调它的假DllMain上的EXE(我不知道它是否可行);但它可能比在许多情况下手动调用伪DllMain更复杂。(不能在DllMain中加载LoadLibrary)