如果在卸载加载它们的系统范围的挂钩卸载时,如何从所有进程中正确卸载DLL?
来自MSDN:
您可以释放全局钩子 程序使用 UnhookWindowsHookEx,但是这个功能 不释放包含的DLL 挂钩程序。这是因为全球化 钩子程序在中调用 每个应用程序的进程上下文 在桌面上,导致隐含 调用LoadLibrary函数 所有这些过程。因为打电话 到FreeLibrary函数不能 为另一个过程,有 然后没办法释放DLL。该 系统最终释放DLL后 所有进程明确链接到 DLL已终止或被调用 FreeLibrary和所有进程 被称为钩子程序已经恢复 处理DLL外部。
所以我正在寻找的是一种方法来检测钩子何时解开,然后从钩住的所有进程中调用FreeLibrary
。有没有其他方法可以在卸载挂钩时立即卸载DLL?
答案 0 :(得分:4)
Hook dll在其消息循环中被卸载。强制它们传入消息循环有助于卸载它们。
在UnhookWindowsHookEx之后添加此项以强制唤醒所有消息循环:
DWORD dwResult;
SendMessageTimeout(HWND_BROADCAST, WM_NULL, 0, 0, SMTO_ABORTIFHUNG|SMTO_NOTIMEOUTIFNOTHUNG, 1000, &dwResult);
但我仍然经常遇到这个问题。我不知道它来自哪里。我想一个锁定的进程可能会阻止dll卸载,但我没有证明这一点。
答案 1 :(得分:1)
一般情况下,如果FreeLibrary
不是必需的,则应使用全局窗口挂钩。如果您确实想这样做,可以使用DLL注入(请参阅例如http://www.codeproject.com/KB/threads/winspy.aspx和http://www.codeproject.com/KB/system/hooksys.aspx)关于CreateRemoteThread
和LoadLibrary
技术。在这种情况下,您可以在远程过程中执行您想要的操作。您可以结合使用这两种技术。
如果您只想调用FreeLibrary
来更新DLL,可以通过其他方式执行此操作。每个加载的DLL都可以重命名(例如在cmd.exe中)为临时名称,您可以使用MoveFileEx
标志调用MOVEFILE_DELAY_UNTIL_REBOOT
。然后,您可以复制并使用新版本的DLL。旧计算机DLL将在下次重新启动计算机时删除。