vb.net使用hook技术之键盘鼠标钩子

Hook 概述:

关于Hook技术的讲解,我还没那能力讲的全面,但是大致了解的就是,它是一种监控的技术,通过挂载钩子,我们能够监控系统中的各种消息来往,以及拦截处理。甚至可以将应用程序注入进程。具体请百度,这里主要讲解如何用vb.net做全局键盘鼠标钩子。

Hook的大致过程

我看了微软和各位大佬博客关于SetWindowsHookEx的讲解,大致的过程就是,将应用程序的定义的钩子安装 钩子链中,这个钩子链就是个链表结构,那么window消息就是从这链表结构中走过去的,就好像是一条河,window消息就像河里的鱼,钩子就像是打鱼的人,一条河有多个打鱼的人,但是这里有个特点,新加入的钩子有优先控制权,什么意思呢,就是新加入的钩子处于旧钩子前面,消息先经过新的钩子,就好像你新加入河边打鱼,你处于上游,所以呢,你不要的消息你得传下去,要不然后面的钩子得不到消息的,比如你会发现你勾住键盘后,不用CallNextHookEx往下传,那么后面的就没有相应的消息,微软也说了,除非你是真的不想要别人得到你的消息,否则建议往下传。钩子挂上了,具体怎么处理呢?所以这里就得假如一个钩子处理函数,就好像你有鱼了,你应该怎么煮呢?所以你会发现安装钩子的函数里有个函数地址的参数,这个函数地址,告诉系统,调用这个函数,把消息放到这里让我处理,我处理完了再给你返回去所谓的回调,即是如此了,在vb.net里用委托代替,当然用Inptr替代也可以只是稍微麻烦点。用完后记得用UnhookWindowsHookEx把钩子卸载了,不卸载就好像你占着茅坑不拉屎一样,影响别人打鱼的进度。影响系统的性能,所以建议用完卸载。
总结一下:安装钩子->送上处理函数HookProc->系统回调处理函数->传递相关参数->用户在处理函数内部处理消息->传递下个钩子->卸载钩子。

Vb.net示例代码

封装一个类Hook


    Public Class Hook
		 <DllImport("kernel32")>
    Public shared Function GetModuleHandle(lpModuleName As String) As IntPtr

    End Function
        Private Const WM_KEYDOWN = &H100 '键按下
        Private Const WM_KEYUP = &H101 '键弹起
        Private Const WM_SYSKEYDOWN = &H104 '全局系统按键
        ''' <summary>
        ''' 鼠标钩子结构体
        ''' </summary>
        ''' <remarks></remarks>
        <StructLayout(LayoutKind.Sequential)>
        Public Structure tagMSLLHOOKSTRUCT
            Dim Pt As Point '鼠标坐标
            Dim mouseData As Integer '鼠标按键数据
            Dim flags As Integer
            Dim time As Integer
            Dim dwExtraInfo As ULong
        End Structure

        ''' <summary>
        ''' 键盘信息
        ''' </summary>
        ''' <remarks></remarks>
        <StructLayout(LayoutKind.Sequential)>
        Public Structure tagKBDLLHOOKSTRUCT
            Dim vkCode As Keys '虚拟按键代码
            Dim scanCode As Keys  '硬件键盘代码
            Dim flags As Integer
            Dim time As Integer '消息时间
            Dim dwExtraInfo As ULong
        End Structure
        ''' <summary>
        ''' WH_MSGFILTER钩子ncode代码枚举
        ''' </summary>
        ''' <remarks></remarks>
        Public Enum MsgncodeType
            ''' <summary>
            ''' 对话框
            ''' </summary>
            ''' <remarks></remarks>
            MSGF_DIALOGBOX = 0
            ''' <summary>
            ''' 菜单
            ''' </summary>
            ''' <remarks></remarks>
            MSGF_MENU = 2
            ''' <summary>
            ''' 滚动条
            ''' </summary>
            ''' <remarks></remarks>
            MSGF_SCROLLBAR = 5

        End Enum
        <StructLayout(LayoutKind.Sequential)>
        Public Structure Msg
            Dim hwnd As Integer
            Dim message As UInteger
            Dim wParam As Integer
            Dim lParam As Integer
            Dim time As Integer
            Dim pt As Point

        End Structure

         Public Event HookEvent(hooktype As HookType,byref handle as boolean, nCode As Integer, wParam As Integer, lParam As IntPtr)
        dim handle  as boolean
        '''钩子处理函数
        Private Function HookProc(nCode As Integer, wParam As Integer, lParam As IntPtr) As IntPtr
           'handle 为用户设置,默认为false即不拦截消息
            RaiseEvent HookEvent(hktype,handle, nCode ,wParam ,lParam ) '此处通过事件递送参数
        if handle  then '取决于用户是否拦截消息
       		 return 1         '拦截直接返回,不传入下个钩子
        End if
        
            Return CallNextHookEx(hookvalue, nCode, wParam, lParam) '直接调用下一个钩子
        End Function
        Private hookvalue As Integer '临时储存一个安装成功钩子的值,以便卸载
        Private myproc As Proc
        Private hktype As HookType '储存钩子类型以便触发事件传入类型
        Public Sub 安装钩子(ByVal 钩子类型 As HookType)
            hktype = 钩子类型
            myproc = New Proc(AddressOf HookProc)
            hookvalue = SetWindowsHookEx(钩子类型, myproc, GetModuleHandle(Process.GetCurrentProcess().MainModule.ModuleName), 0) '安装钩子,默认为全局钩子
 
            If hookvalue = 0 Then
                UnhookWindowsHookEx(hookvalue)
            End If
        End Sub
        Public Sub 卸载钩子()
            UnhookWindowsHookEx(hookvalue)
        End Sub
        ''' <summary>
        ''' 处理委托
        ''' </summary>
        ''' <param name="nCode">Ncode小于零要调用callnext</param>
        ''' <param name="wParam"></param>
        ''' <param name="lParam"></param>
        ''' <returns></returns>
        ''' <remarks></remarks>
        Public Delegate Function Proc(nCode As Integer, wParam As Integer, lParam As IntPtr) As Integer
        Public Enum HookType
            ''' <summary>
            ''' 处理消息前钩子CallWndProc挂钩处理过程
            ''' </summary>
            ''' <remarks></remarks>
            WH_CALLWNDPROC = 4
            ''' <summary>
            ''' 对已被目标窗口处理过程处理过了的消息进行监视CallWndRetProc 挂钩处理过程
            ''' </summary>
            ''' <remarks></remarks>
            WH_CALLWNDPROCRET = 12
            ''' <summary>
            ''' 前台程序空闲时调用
            ''' </summary>
            ''' <remarks></remarks>
            WH_FOREGROUNDIDLE = 11
            ''' <summary>
            ''' 监控发送的消息,寄送至消息队列的消息进行监视,详情参见 GetMsgProc 挂钩处理过程.
            ''' </summary>
            ''' <remarks></remarks>
            WH_GETMESSAGE = 3
            ''' <summary>
            ''' 安装一个挂钩处理过程,对此前由WH_JOURNALRECORD 挂钩处理过程纪录的消息进行寄送.详情参见 JournalPlaybackProc挂钩处理过程.
            ''' </summary>
            ''' <remarks></remarks>
            WH_JOURNALPLAYBACK = 1
            ''' <summary>
            ''' 安装一个挂钩处理过程,对寄送至系统消息队列的输入消息进行纪录.详情参见JournalRecordProc挂钩处理过程
            ''' </summary>
            ''' <remarks></remarks>
            WH_JOURNALRECORD = 0
            ''' <summary>
            ''' 安装一个挂钩处理过程对击键消息进行监视. 详情参见KeyboardProc挂钩处理过程
            ''' </summary>
            ''' <remarks></remarks>
            WH_KEYBOARD = 2
            ''' <summary>
            ''' 此挂钩只能在Windows NT中被安装,用来对底层的键盘输入事件进行监视.详情参见LowLevelKeyboardProc挂钩处理过程.
            ''' </summary>
            ''' <remarks></remarks>
            WH_KEYBOARD_LL = 13
            ''' <summary>
            ''' 安装一个挂钩处理过程,对鼠标消息进行监视.  详情参见 MouseProc挂钩处理过程.
            ''' </summary>
            ''' <remarks></remarks>
            WH_MOUSE = 7
            ''' <summary>
            ''' 此挂钩只能在Windows NT中被安装,用来对底层的鼠标输入事件进行监视.详情参见LowLevelMouseProc挂钩处理过程.
            ''' </summary>
            ''' <remarks></remarks>
            WH_MOUSE_LL = 14
            ''' <summary>
            ''' 安装一个挂钩处理过程, 以监视由对话框、消息框、菜单条、或滚动条中的输入事件引发的消息.详情参见MessageProc挂钩处理过程.
            ''' </summary>
            ''' <remarks></remarks>
            WH_MSGFILTER = -1
            ''' <summary>
            ''' 安装一个挂钩处理过程以接受对外壳应用程序有用的通知, 详情参见 ShellProc挂钩处理过程.
            ''' </summary>
            ''' <remarks></remarks>
            WH_SHELL = 10
            ''' <summary>
            ''' 安装一个挂钩处理过程,以监视由对话框、消息框、菜单条、或滚动条中的输入事件引发的消息.这个挂钩处理过程对系统中所有应用程序的这类消息都进行监视.详情参见 SysMsgProc挂钩处理过程.
            ''' </summary>
            ''' <remarks></remarks>
            WH_SYSMSGFILTER = 6

        End Enum
        '安装钩子
        'Hook为钩子类型,lpfn为函数指针,指向需要执行的函数,hIntance为指向进程块的指针,threadId默认为0就可以了
        ''' <summary>
        ''' 安装钩子
        ''' </summary>
        ''' <param name="Hook">钩子类型</param>
        ''' <param name="lpfn">处理函数</param>
        ''' <param name="hInstance">进程模块</param>
        ''' <param name="threadId">线程ID设为0表示全局</param>
        ''' <returns></returns>
        ''' <remarks></remarks>
        <DllImport("user32.dll")> _
        Private Shared Function SetWindowsHookEx(Hook As HookType, lpfn As Proc, hInstance As IntPtr, threadId As Integer) As Integer
        End Function
        '取消钩子
        <DllImport("user32.dll", CharSet:=CharSet.Auto, CallingConvention:=CallingConvention.StdCall)> _
        Public Shared Function UnhookWindowsHookEx(idHook As Integer) As Boolean
        End Function

        '调用下一个钩子
        <DllImport("user32.dll")> _
        Public Shared Function CallNextHookEx(idHook As Integer, nCode As Integer, wParam As Integer, lParam As IntPtr) As Integer
        End Function
    End Class
 

调用

Dim WithEvents hk As New Hook
Private Sub Form1_FormClosing(sender As Object, e As System.Windows.Forms.FormClosingEventArgs) Handles Me.FormClosing
    hk.卸载钩子()
End Sub

Private Sub Form1_Load(sender As Object, e As System.EventArgs) Handles Me.Load

    hk.安装钩子(Hook.HookType.WH_MOUSE_LL) '类型选择鼠标钩子,要键盘可选择键盘钩子,都有说明

End Sub

    Private Sub hk_HookEvent(hooktype As Hook.HookType, byref handle as boolean, nCode As Integer, wParam As Integer, lParam As IntPtr) Handles hk.HookEvent   
       Dim b As Hook.tagMSLLHOOKSTRUCT = Marshal.PtrToStructure(lParam, GetType(Hook.tagMSLLHOOKSTRUCT)) '转为结构体,如若键盘钩子请选择键盘钩子的结构体,具体看hook类。
        Me.Text = b.Pt.ToString
    End Sub

效果如图
鼠标钩子演示
以上就是钩子的全部代码,这里有个要注意的点,必须声明一个全局消息处理委托变量储存,要不然会导致委托被回收而导致程序崩溃

  • 7
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
C#使用全局鼠标键盘Hook需要使用Win32 API来实现,以下是一个简单的示例代码: ```csharp using System; using System.Diagnostics; using System.Runtime.InteropServices; namespace GlobalHookDemo { class Program { private delegate IntPtr LowLevelKeyboardProc(int nCode, IntPtr wParam, IntPtr lParam); [DllImport("user32.dll", SetLastError = true)] private static extern IntPtr SetWindowsHookEx(int idHook, LowLevelKeyboardProc lpfn, IntPtr hMod, uint dwThreadId); [DllImport("user32.dll", SetLastError = true)] private static extern bool UnhookWindowsHookEx(IntPtr hhk); [DllImport("user32.dll", SetLastError = true)] private static extern IntPtr CallNextHookEx(IntPtr hhk, int nCode, IntPtr wParam, IntPtr lParam); [DllImport("kernel32.dll", SetLastError = true)] private static extern IntPtr GetModuleHandle(string lpModuleName); private const int WH_KEYBOARD_LL = 13; private static LowLevelKeyboardProc _proc = HookCallback; private static IntPtr _hookID = IntPtr.Zero; static void Main(string[] args) { _hookID = SetHook(_proc); Console.WriteLine("Global keyboard hook installed."); Console.WriteLine("Press any key to exit."); Console.ReadKey(); UnhookWindowsHookEx(_hookID); } private static IntPtr SetHook(LowLevelKeyboardProc proc) { using (Process curProcess = Process.GetCurrentProcess()) using (ProcessModule curModule = curProcess.MainModule) { return SetWindowsHookEx(WH_KEYBOARD_LL, proc, GetModuleHandle(curModule.ModuleName), 0); } } private static IntPtr HookCallback(int nCode, IntPtr wParam, IntPtr lParam) { if (nCode >= 0 && wParam == (IntPtr)0x100) { int vkCode = Marshal.ReadInt32(lParam); Console.WriteLine((Keys)vkCode); } return CallNextHookEx(_hookID, nCode, wParam, lParam); } } } ``` 这个示例代码可以监听全局键盘事件并输出键码。如果需要监听鼠标事件,可以使用`SetWindowsHookEx`函数的第一个参数`idHook`设置为`WH_MOUSE_LL`。需要注意的是,全局Hook会影响系统性能,使用时需要谨慎。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值