键盘钩子失灵

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了键盘钩子失灵相关的知识,希望对你有一定的参考价值。

自编的一个VB键盘钩子程序,工作良好,但是只要新开一个IE窗口或是新开一个IE的Tab(Ctrl-T),就出现钩子失灵,表现为捕捉不到任何按键信息,但是只要这个IE窗口关闭,或是这个New IE Tab关闭后,钩子又恢复正常。这是何道理? 是不是每次新打开一个IE,系统会重定向键盘消息处理进程或线程?然后原来的钩子就失效了?
我现在的办法是定时监测当前窗口的句柄是否在下钩之前存在,如果存在,无动作,如果是新的窗口,卸钩 再下钩子。 不过这种办法对于NEW TAB的情况无效,因为窗口句柄未变化。
哪位大侠有这方面的心得?
忘了说了,我的环境 WindowsXP SP3, IE 8.0,钩子是VB作的。
我说的钩子工作良好,是指在下钩之后,新开IE之前,所有的按键信息都能捕捉,包括桌面的和任何其他程序的按键。

1 楼的760578568 兄弟,麻烦你敬业一点好不好。你会百度,难道我不会百度?

VB编程中钩子的实现及应用

Windows系统中钩子具有相当强大的功能,通过这种技术可以对几乎所有的Windows 系统中的消息进行拦截、监视、处理。这种技术可以广泛应用于各种软件,尤其是需要有监控、自动记录等对系统进行监测功能的软件。本文针对这个专题进行了探讨,希望可以为读者朋友们起到抛砖引玉的作用。

一、钩子的机制及类型

Windows的应用程序都是基于消息驱动的,应用程序的操作都依赖于它所得到的消息的类型及内容。钩子与Dos中断截获处理机制有类似之处。钩子(Hook)是Windows消息处理机制的一个平台,通过安装各种钩子,应用程序可以在上面设置子程序以监视指定窗口的某种消息,并且当消息到达目标窗口之前处理它。

在Windows中,钩子有两种,一种是系统钩子(RemoteHook),它对消息的监视是整个系统范围,另一种是线程钩子(LocalHook),它的拦截范围只有进程内部的消息。对于系统钩子,其钩子函数(HookFunction)应在Windows系统的动态链接库(DLL)中实现,而对于线程钩子来说,钩子函数可以在DLL之中实现,也可以在相应的应用程序之中实现。这是因为当开发人员创建一个钩子时,Windows先在系统内存中创建一个数据结构,该数据结构包含了钩子的相关信息,然后把该结构体加到已经存在的钩子链表中去,并且新的钩子将排在老的钩子的前面。当一个事件发生时,如果安装的是一个局部钩子,当前进程中的钩子函数将被调用。如果是一个远程钩子,系统就必须把钩子函数插入到其它进程的地址空间,要做到这一点就要求钩子函数必须在一个动态链接库中,所以如果想要使用远程钩子,就必须把该钩子函数放到动态链接库中去。对于钩子所监视的消息类型来说,Windws一共提供了如下几种类型:如表1所示:

表一、Windows消息类型

消息类型常量标识



消息类型

适用范围

WH_CALLWNDPROC

4

发给窗口的消息

线程或系统

WH_CALLWNDPROCRET

12

窗口返回的消息

线程或系统

WH_CBT

5

窗口变化、焦点设定等消息

线程或系统

WH_DEBUG

9

是否执行其它Hook的Hook

线程或系统

WH_FOREGROUNDIDLE

11

前台程序空闲

线程或系统

WH_GETMESSAGE

3

投放至消息队列中的消息

线程或系统

WH_JOURNALPLAYBACK

1

将所记载的消息进行回放

系统

WH_JOURNALRECORD

0

监视并记录输入消息

系统

WH_KEYBOARD

2

键盘消息

线程或系统

WH_MOUSE

7

鼠标消息

线程或系统

WH_MSGFILTER

-1

菜单滚动条、对话框消息

线程或系统

WH_SHELL

10

外壳程序的消息

线程或系统

WH_SYSMSGFILTER

6

所有线程的菜单滚动条、对话框消息

系统

二、VB编程中钩子的实现

(一)钩子函数(HOOK Function)的格式。Hook Function实际上是一个函数,如果是系统钩子,该函数必须放在动态链接库中。该函数有一定的参数格式,在VB中如下:

Private Function HookFunc(ByVal nCode As Long,ByVal wParam As Long,ByVal lParam As Long)As Long

其中,nCode代表是什么情况之下所产生的钩子,随钩子的不同而有不同组的可能值;参数wParam,lParam传回值包括了所监视到的消息内容,它随Hook所监视消息的种类和nCode的值不同而不同。对于用VB所设置的钩子函数,一般的框架形式如下:

Private Function HookFunc(ByVal nCode As Long,ByVal wParam As Long,ByVal lParam As Long)As Long

Select case of nCode

case ncode<0:hookfunc=callnexthookex(hHookFunc,nCode,wParam,lParam)

case值1:处理过程1:HookFunc=X1

case2:处理过程2:HookFunc=X1

……

end select

end Function

函数的传回值,如果消息要被处理,则传0,否则传1,吃掉消息。

(二)钩子的安装及执行。钩子的安装要用到几个API函数:可以使用API函数SetWindowsHookEx()把一个应用程序定义的钩子子程安装到钩子链表中。SetWindowsHookEx()函数的声明如下:

Declare function SetWindowsHookEx Lib "user32" Alias "SetWindowsHookExA"(ByVal idHook As Long,ByVal lpfn As Long,ByVal hmod As Long,ByVal dwThreadId As Long)As Long

idHook值为它处理的消息类型;lpfn值为钩子子程序的地址指针。如果dwThreadId参数为0或是一个由别的进程创建的线程的标识,lpfn必须指向DLL中的钩子子程。除此以外,lpfn可以指向当前进程的一段钩子子程代码。hMod值为应用程序的句柄,标识包含lpfn所指的子程的DLL。如果dwThreadId标识当前进程创建的一个线程,而且子程代码位于当前进程,hMod必须为0。dwThreadId值为与安装的钩子子程相关联的线程的标识符,如果为0,钩子子程与所有的线程关联。钩子安装成功则返回钩子子程的句柄,失败返回0。

另外,一般应在钩子子程中调用CallNextHookEx()函数以执行钩子链表所指的下一个钩子子程,否则安装了别的钩子的应用程序就会收不到钩子通知,从而产生错误的结果。CallNextHookEx()函数的声明如下:

Declare Function CallNextHookEx Lib"user32" Alias "CallNextHookEx"(ByVal hHook As Long,ByVal ncode As Lonog, ByVal wParam As Long,lParam As Any)As Long

hHook值是SetWindowsHookEx()的传回值,nCode、wParam、lParam则是Hook函数中的三个参数。在程序终止之前,必须调用UnhookWindowsHookEx()函数释放与钩子关联的系统资源。UnhookWindowsEx()函数声明如下:

Declare Function Unhook WindowsHookEx Lib "user32" Alias "Unhook WindowsHookEx(ByVal hHook As Long)As Long

hHook为安装钩子时的返回值,即钩子子程的句柄。

(三)VB中钩子安装应注意的问题。lpfn参数是一个HookFunc的地址,VB规定必须将HookFunc代码放到标准的.BAS模块中,并以"Address Of HookFunc"传入,而不可以将其放到类模块中,也不能将其附加到窗体上。而对于RemoteHook来说,HookFunc应包含在动态链接库中,因此如果在VB中使用RemoteHook,则还要用到GetModuleHandle()、GetProcAddress()两个API函数,它们的声明如下:

Declare Function GetModuleHandle Lib"kernel32" Alias "GetModuleHandleA"(ByVal lpModuleName As String)As Long

Declare Function GetProcAddress Lib "kernel32" Alias "GetProcAddress"(ByVal hModule As Long,ByVal lpProcName As String)As Long

hmod值是含钩子过程的模块名柄,如果是LocalHook,该值可以是Null(VB中传0),而如果是RemoteHook,则可以使用GetModuleHandle("名称.dll")来传入。

三、实例--键盘消息的拦截

在程序开发时常用的有对输入消息进行监视的键盘钩子,对于所监视到的消息应进行处理,下面对键盘钩子参数的具体内容组成进行说明:

如果有键盘消息(WM_KEYUP或WM_KEYDOWN)将被处理时,则系统调用键盘钩子。

nCode为HC_ACTION或HC_NOREMOVE,若小于0,则要求处理函数向下传递该消息。

wParam表示按键键码常数,A键到Z键与其ASCII码的相应值'A'到'Z'是一致的,例如按C键,则wParam值为67。

lParam与WM_KEYDOWN同,占四个字节,其包括的内容较多,其二进制结构如下:

0

1

……

15

16

………

23

24

25

……

28

29

30

31

0-15位(Key repeat count),键码重复次数。16-23位(Scan code),按键的扫描码。24位(Extended_Key flag),扩展键(功能键、数字小键盘上的键)标志,为1则是扩展键,否则为0。25-28位被保留。29位(Context Code),状态描述码,ALT键被按下则为1,否则为0。30位(Previouskey_stateflag)指定先前的键状态,如果消息被发出之前键处于按下状态,则为1;键处于释放状态则为0。31位(Transiton_stateflag)状态转换标志,如果键是被按下值为1,如果键被放开值为0。

本例中的钩子用来监视并记录应用程序中的按键信息。在程序中,ALT+F4组合键被屏蔽。下面是部分代码:

Public hHook as Long

Private Sub Form_Load()′程序启动时安装钩子

hHook=SetWindowsHookEx(2,Address of MyKBHook,0,App.ThreadID)

End Sub

′具体的钩子程序,本例中该过程被包含在Module1中

Public Function MyKBHook(ByVal nCode As Long,ByVal wParam As Long,ByVal lParam As Long)As Long

If nCode>=0 then

Open "C:\Keyfile.txt" For Append As #1 '将键盘的操作记录在Keyfile.txt文件之中

'记录所操作的键、操作时间、日期操作时的按键状态,用16进制记录

Write #1,wParam,Hex(lParam),Date,time

Close #1

MyKBHook=0 '表示要处理这个消息

'屏蔽ALT+F4组合键

if wParam=115 And(lParam And&H20000000)<>0 Then

if(lParam And &HC000000)=0 Then '是否进行ALT+F4操作

MyHBHook=1 '钩子吃掉这个消息

End if

End if

End if

Call CallNextHookEx(hHook,nCode,wParam,lParam)'将消息传给下一个钩子

End Function

'程序退出时卸载钩子

Private Sub Form_Unload(Cancel As Interger)

Call Unhook WindowsHookEx(hHook)

End Sub

四、总结

钩子处理程序是Windows高级编程技术,一般程序员都使用VC++等程序设计工具实现,本文表明,对于VB来说,虽然很多人认为是非专业的设计工具,但实现钩子这样的高级技术也是非常方便的。另外在使用钩子时应注意到,钩子虽然功能比较强,但如果使用不当将会严重影响系统的效率,所以要尽量避免使用系统钩子,并且在不用钩子时,应将钩子及时卸载。
这些当中出现了矛盾
祝你早日解决
参考技术A XPSP3居然用了IE8,手动升级的么?
你可以换机器试一下7.0或以下的会不会出现这样的问题。

问题是否也在IE core的其它浏览器上出现?

现在新一代的很多浏览器的标签都直接做成进程了(不知道包不包括IE8),比如世界之窗的混合进程模式,也许这样会有影响
参考技术B 一般这种问题都很难回答的,太多可能,好好检查程序吧 参考技术C 1楼 太假了。不过LZ这种情况也是比较复杂,不好说阿。 参考技术D 不会把

解决macbook键盘失灵问题

员工告知macbook无法使用键盘。

经排查f1-f12可用,切换到win7系统键盘可用,排除硬件问题。

后经排查问题出在输入法上,删除搜狗输入法后,一切正常。


以上是关于键盘钩子失灵的主要内容,如果未能解决你的问题,请参考以下文章

键盘钩子怎么 使用

delphi键盘钩子没效果

c++实现键盘记录仪(键盘钩子)

C# WinForm键盘钩子

VC 键盘钩子问题

delphi 键盘全局钩子