我有一个特殊的要求,我相信没有其他办法,那就是:检测DLL的卸载。 我search了一下,发现了一个四年的SO 。 我select了相同的解决scheme:钩免费库。
当代码进入MyFreeLibrary
,我将以同样的方式挂钩指定模块的入口点(内联钩子)。 而在MyEntryPoint
,我将首先调用原始入口点,然后检查reason
参数 – 如果值等于DLL_PROCESS_DETACH
,则意味着该DLL的清理工作刚刚完成,并且将从地址空间中卸载。 在这一点上,我有机会做我的工作。 有用。
就是这样了 ? 不幸的是,它还没有完成。 一个非常重要的事情被忽视:依赖。
例如, a.dll
链接对b.dll
和c.dll
。 加载a.dll
, b.dll
和c.dll
将首先被加载(被初始化)。 这是因为b.dll
和c.dll
在c.dll
的导入表中a.dll
,它们是a.dll
依赖关系。 同样,卸载a.dll
,如果引用计数减less到零, b.dll
和c.dll
也可能会被卸载。 我不知道有关加载程序如何发现DLL的依赖关系并将其卸载的详细信息, FreeLibrary
的MSDN页面没有提到这一点,我很高兴明白这一点,但是我没有find信息。
所以主要的问题是如何检测卸载DLL模块的依赖关系。 我想有同样的机会去做我的工作。
一个可能的解决scheme可能是导入表,从它的导入表中找出一个DLL的依赖关系,并从它们的导入表中找出依赖关系的依赖关系,找出所有依赖关系,钩住所有入口点,不知道,这听起来很疯狂,我需要一些build议。
我为旧的SO问题提供了答案。 你现在写:
而在MyEntryPoint中,我将首先调用原始入口点,然后检查原因参数 – 如果值等于DLL_PROCESS_DETACH,则意味着该DLL的清理工作刚刚完成,并且将从地址空间中卸载。
你已经发现这是不正确的。 但最简单的解决方法是什么? 如果在找到原因是DLL_PROCESS_DETACH之后,你会测试hmodulee是否仍然有效? 看到:
如何判断Windows模块句柄是否仍然有效?
您可能可以跳过钩入DLL入口点,而不是检查DLL_PROCESS_DETACH,并且总是测试hmodulee是否仍然有效。 这让我意识到,最好在调用原始FreeLibrary之前检查hmodulee是否有效,然后再测试一个有效的无效转换:
if (moduleWasValid && !moduleStillValid) { // process module unloaded }
我希望这有帮助。