Windows全局钩子实现方案回顾
来源:互联网 发布:中医宝典大全软件 编辑:程序博客网 时间:2024/06/03 19:51
首先声明此文没有任何新的地方,俗话说阳光之下无原创。写下这个短文仅仅是对前几天做的一个小事情的总结,也许有可能对一些初学者起到一定的帮助作用,则善莫大焉。
先看任务要求:需要实现全局的鼠标钩子,但是是在后台运行的,希望安装程序之后在系统启动时自动启动,并且监视一个具体的设备,当该设备插入时,启动全局钩子;当该设备从系统删除时,撤销全局钩子。非常简单的一句话概括了任务。
再看解决方案:当拿到这个任务的时候,我们大概的解决思路和关键技术在于几个方面:1. 钩子技术的实现,包括钩子的创建和撤销,因为是鼠标钩子所以牵涉到动态连接库的实现和调用;2.后台运行的实现,直接想法应该是应用windows服务程序,这样的程序可以在系统启动是自动启动并且运行于后台。
钩子DLL没有什么难题,不进行详细解释。关于windows服务程序的实现,需要监视设备的插入/删除,另外这样的程序的调试也稍稍有点不同,就是在debug的菜单里面,关联process来进行调试。实现设备的监视关键代码如下:
ServiceMain(DWORD dwArgc, PWSTR *pszArgv){Sleep(3000); // Register the handler function for the service RegisterServiceCtrlHandlerEx( s_service->m_name,(LPHANDLER_FUNCTION_EX)ServiceCtrlHandler, 0); if (s_service->m_statusHandle == NULL) { throw GetLastError(); } // Start the service. s_service->Start(dwArgc, pszArgv);// Register the device change notification DEV_BROADCAST_DEVICEINTERFACE NotificationFilter;ZeroMemory( &NotificationFilter, sizeof(NotificationFilter) );NotificationFilter.dbcc_size = sizeof(DEV_BROADCAST_DEVICEINTERFACE);NotificationFilter.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE;memcpy( &(NotificationFilter.dbcc_classguid),&(GUID_DEVINTERFACE_USB),sizeof(struct _GUID));HDEVNOTIFY hDevNotify = RegisterDeviceNotification(s_service->m_statusHandle, &NotificationFilter,DEVICE_NOTIFY_SERVICE_HANDLE|DEVICE_NOTIFY_ALL_INTERFACE_CLASSES);}
在相应的serviceHandler里面有如下的代码:
void WINAPI CServiceBase::ServiceCtrlHandler(DWORD dwCtrl,DWORD evtype, PVOID evdata, PVOID Context){ switch (dwCtrl) { case SERVICE_CONTROL_STOP: s_service->Stop(); break; case SERVICE_CONTROL_PAUSE: s_service->Pause(); break; case SERVICE_CONTROL_CONTINUE: s_service->Continue(); break; case SERVICE_CONTROL_SHUTDOWN: s_service->Shutdown(); break; case SERVICE_CONTROL_DEVICEEVENT: s_service->DeviceEventNotify(evtype, evdata); break; case SERVICE_CONTROL_INTERROGATE: break; default: break; }}
DeviceEventNotify函数如下:
unsigned long DeviceEventNotify(DWORD evtype, PVOID evdata){HINSTANCE hmodule = LoadLibrary(_T("MouseHookDLL.dll"));if (hmodule == NULL){WriteToLog("DLL Load Failed.");FreeLibrary(hmodule);return 0;}typedef HHOOK (*pInstallHook)(HINSTANCE hmodule);typedef BOOL (*pUnInstallHook)(HHOOK hook);pInstallHook InstallHookFunction = (pInstallHook) GetProcAddress(hmodule, "InstallHook");pUnInstallHook UnInstallHookFunction = (pUnInstallHook) GetProcAddress(hmodule, "UnInstallHook");switch (evtype){case DBT_DEVICEREMOVECOMPLETE:{// Stop the HookWriteToLog("Remove USB Device.");UnInstallHookFunction(hook);}break;case DBT_DEVICEARRIVAL:{// Create a Hook to reset the cursorWriteToLog("Insert USB Device.");hook = InstallHookFunction(hmodule);}break;}FreeLibrary(hmodule);return 0;}
道理上上面的方案应该是可行的,但是程序调试发现,虽然DLL可以正确的load但是,确调用不到DLL的callback函数,查阅资料之后发现,windows不允许服务程序实现全局钩子。说明此种方案行不通。那么我们考虑第二种方案,就是利用一个windows后台程序实现设备的插入/删除监视功能,并且在里面调用相应的DLL。这个也不是难题,但是怎么实现后台运行是我们这个时候需要考虑的问题,解决方法也很简单,就是把这个windows的窗口的show里面的参数改为SW_HIDE.
{ DEV_BROADCAST_DEVICEINTERFACE NotificationFilter; ZeroMemory( &NotificationFilter, sizeof(NotificationFilter) ); NotificationFilter.dbcc_size = sizeof(DEV_BROADCAST_DEVICEINTERFACE); NotificationFilter.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE; NotificationFilter.dbcc_classguid = InterfaceClassGuid; *hDeviceNotify = RegisterDeviceNotification( hWnd, // events recipient &NotificationFilter, // type of device DEVICE_NOTIFY_ALL_INTERFACE_CLASSES|DEVICE_NOTIFY_WINDOW_HANDLE // type of recipient handle ); if ( NULL == *hDeviceNotify ) {ErrorHandler(TEXT("RegisterDeviceNotification")); return FALSE; } return TRUE;}
// Main app window HWND hWnd = CreateWindowEx( WS_EX_CLIENTEDGE | WS_EX_APPWINDOW, WND_CLASS_NAME, g_pszAppName, WS_OVERLAPPEDWINDOW, // style CW_USEDEFAULT, 0, 640, 480, NULL, NULL, hInstanceExe, NULL); if ( hWnd == NULL ) {ErrorHandler(TEXT("CreateWindowEx: main appwindow hWnd")); return -1; } // Actually draw the window. ShowWindow(hWnd, SW_HIDE); UpdateWindow(hWnd);
总结:
总体方法就是在windows service程序不允许全局钩子的情况下,创建隐藏窗口的windows应用程序实现全局钩子。
- Windows全局钩子实现方案回顾
- Windows 全局 鼠标 钩子 DLL
- Windows 全局钩子 Hook 详解
- Delphi实现全局鼠标钩子
- Windows全局钩子dll(键盘)
- windows全局消息钩子的一个BUG
- Windows全局钩子dll(键盘)
- windows函数钩子实现
- windows函数钩子实现
- Win32全局钩子在VC5中的实现
- Win32全局钩子在VC5中的实现
- Win32全局钩子在VC5中的实现
- 全局钩子实现键盘按键替换
- vc全局钩子实现程序监控
- VC实现的全局键盘钩子
- win7下全局低层键盘钩子实现
- 全局钩子
- 全局钩子
- OCP-043 drop diskgroup
- Ubuntu Server 11.10 安装Redmine 1.4
- vs2010中工具箱不出现ArcGIS Windows Forms怎么办?
- 如何申请Android MapView的apiKey
- wordpress多站点设置
- Windows全局钩子实现方案回顾
- IOS 动画例子(Path 菜单按钮)
- 设置asp.net中的复选框列表的显示样式的方法
- 一个XML解析失败排查过程的分享
- ios资源库
- ArchLinux 安装一些软件包
- Jquery 日程安排 fullcalender 的使用
- 关于ext读取json字符串中的某个属性的值
- Thinking in Hibernate Configuration Class