在取消全局CBT挂钩后从所有进程卸载DLL

时间:2010-07-02 08:26:38

标签: winapi setwindowshookex unhookwindowshookex

如果在卸载加载它们的系统范围的挂钩卸载时,如何从所有进程中正确卸载DLL?

来自MSDN

  

您可以释放全局钩子   程序使用   UnhookWindowsHookEx,但是这个功能   不释放包含的DLL   挂钩程序。这是因为全球化   钩子程序在中调用   每个应用程序的进程上下文   在桌面上,导致隐含   调用LoadLibrary函数   所有这些过程。因为打电话   到FreeLibrary函数不能   为另一个过程,有   然后没办法释放DLL。该   系统最终释放DLL后   所有进程明确链接到   DLL已终止或被调用   FreeLibrary和所有进程   被称为钩子程序已经恢复   处理DLL外部。

所以我正在寻找的是一种方法来检测钩子何时解开,然后从钩住的所有进程中调用FreeLibrary。有没有其他方法可以在卸载挂钩时立即卸载DLL?

2 个答案:

答案 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.aspxhttp://www.codeproject.com/KB/system/hooksys.aspx)关于CreateRemoteThreadLoadLibrary技术。在这种情况下,您可以在远程过程中执行您想要的操作。您可以结合使用这两种技术。

如果您只想调用FreeLibrary来更新DLL,可以通过其他方式执行此操作。每个加载的DLL都可以重命名(例如在cmd.exe中)为临时名称,您可以使用MoveFileEx标志调用MOVEFILE_DELAY_UNTIL_REBOOT。然后,您可以复制并使用新版本的DLL。旧计算机DLL将在下次重新启动计算机时删除。