【问题标题】:How do I setup a systemwide hook to listen for WM_DEVICECHANGE?如何设置系统范围的挂钩来监听 WM_DEVICECHANGE?
【发布时间】:2015-05-08 12:56:13
【问题描述】:

我想设置一个系统范围的挂钩以在 C++ 中侦听 WM_DEVICECHANGE。我知道挂钩是使用SetWindowsHookEx() 设置的。我以前为键盘消息(WM_KEYUPWM_KEYDOWN)做过这个,但我想为WM_DEVICECHANGE做这个。我目前正在使用:

#include <windows.h>
#include <tchar.h>
#include <iostream>
void WinHook();
LRESULT CALLBACK HookProc(int nCode, WPARAM wParam, LPARAM lParam);

int _tmain(int argc, _TCHAR* argv[])
{
   WinHook();
   std::cout << GetLastError() << " winhook\n";
   return 0;
}

void WinHook()
{
   HHOOK hook = NULL;
   hook = SetWindowsHookEx(WH_GETMESSAGE, HookProc, NULL, GetCurrentThreadId());
   std::cout << GetLastError() << " sethook\n";
   MSG msg;
   while (GetMessage(&msg, NULL, 0, 0) > 0)
   {
      TranslateMessage(&msg);
      DispatchMessage(&msg);
   }
}
LRESULT CALLBACK HookProc(int nCode, WPARAM wParam, LPARAM lParam){
   std::cout << GetLastError() << " hookproc called\n";
   switch (wParam){
     case WM_DEVICECHANGE: std::cout << "SUCCESS!!!!!"; break;
     default: return CallNextHookEx(NULL, nCode, wParam, lParam);
   }
}

编辑:SetWindowsHookEx() 之后的GetLasterror() 返回0,而函数HookProc() 中的那个永远不会被调用。

【问题讨论】:

  • 该消息被发送到所有顶级窗口,为什么要挂钩?您可以使用 RegisterDeviceNotification() 和隐藏窗口
  • @AlexK。我不想使用隐藏窗口,没必要。
  • 如果有替代方案,我个人认为没有必要安装系统范围的钩子
  • 您使用的是实际代码?我明白为什么它不适合你;如果它不能编译,它就不可能执行,如果它不能执行它就不可能捕捉到消息。如果您希望我们帮助您找出您的代码无法运行的原因,请发布您的实际代码,而不是您在编写问题时临时编造的内容。
  • @KenWhite 不是编的。主要方法我还没贴,就这样吧。

标签: c++ windows winapi hook


【解决方案1】:

您正在为您自己的线程收到的所有消息安装 WindowsHook。

您的程序没有打开任何窗口,也没有收到任何消息。所以钩子不会被调用。

正如其中一个 cmets 所说,您需要创建一个(可能是隐藏的)顶级窗口和RegisterDeviceNotification,您不需要钩子。

另一种方法是安装系统范围的挂钩,但这需要额外的 DLL 和桌面上的任何其他顶级窗口,而且更复杂且更消耗资源。

【讨论】:

  • 无需在 DLL 中创建系统范围的钩子,我的代码可以与同一可执行文件中的 HookProc() 一起正常工作。但该代码侦听 WM_KEYUP。
  • @NabeelOmer,“DBT_DEVICEARRIVALDBT_DEVICEREMOVECOMPLETE 事件会自动广播到端口设备的所有顶级窗口......音量通知也会广播到顶级窗口”。您需要创建一个窗口来查看这些消息。如果您想要特定的设备更改消息,您需要注册才能接收它们。
  • 仅仅因为代码适用于键盘钩子并不意味着它是用于其他钩子的正确代码。阅读文档。您的代码正在为调用线程创建一个 thread-specific 挂钩。您的线程有一个消息循环,但没有用于捕获消息的窗口。这不是创建 global 消息挂钩的正确方法。您必须在 DLL 中实现挂钩,以便将其注入其他进程,并且您必须dwThreadId 参数设置为 0 以挂钩所有线程。
【解决方案2】:

尝试为此使用钩子是错误的。

正确的做法是使用窗口接收消息。如果您手头有一个,也许是一个顶级窗口。或仅消息窗口。顶层窗口将收到基本通知。或者将RegisterDeviceNotification 与仅消息窗口一起使用以接收更全面的通知​​。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-11-12
    • 1970-01-01
    • 2018-07-15
    • 2012-04-30
    • 2010-12-08
    • 2017-10-03
    • 2011-12-10
    相关资源
    最近更新 更多