• 【Net】一个简单的键盘钩子


    最近在写一个采集程序

    需要用到钩子

    为了学习钩子 特写了个小demo

    为实现高级功能的钩子打好基础

    下面是代码

    ----------------

    钩子类型

     1 namespace CSharpHook
     2 {
     3     public enum HookType
     4     {
     5         MsgFilter = -1,
     6 
     7         JournalRecord = 0,
     8 
     9         JournalPlayback = 1,
    10 
    11         Keyboard = 2,
    12 
    13         GetMessage = 3,
    14 
    15         CallWndProc = 4,
    16 
    17         CBT = 5,
    18 
    19         SysMsgFilter = 6,
    20 
    21         Mouse = 7,
    22 
    23         Hardware = 8,
    24 
    25         Debug = 9,
    26 
    27         Shell = 10,
    28 
    29         ForegroundIdle = 11,
    30 
    31         CallWndProcRet = 12,
    32 
    33         KeyboardLL = 13,
    34 
    35         MouseLL = 14
    36     }
    37 }

    钩子核心调用方法

     1 amespace CSharpHook
     2 {
     3     public delegate IntPtr HookProc(int code, IntPtr wparam, IntPtr lparam);
     4     public class CSHook
     5     {
     6         [DllImport("kernel32.dll")]
     7         public static extern int GetCurrentThreadId(); //取得当前线程编号的API
     8 
     9         [DllImport("User32.dll")]
    10         public extern static void UnhookWindowsHookEx(IntPtr handle); //取消Hook的API
    11         
    12         [DllImport("User32.dll")]
    13         public extern static IntPtr SetWindowsHookEx(int idHook, [MarshalAs(System.Runtime.InteropServices.UnmanagedType.FunctionPtr)] HookProc lpfn, IntPtr hinstance, int threadID);  //设置Hook的API
    14 
    15         [DllImport("User32.dll")]
    16         public extern static IntPtr CallNextHookEx(IntPtr handle, int code, IntPtr wparam, IntPtr lparam); //取得下一个Hook的API
    17     }
    18 }

     钩子业务调用类

     1 namespace CSharpHook
     2 {
     3     public abstract class MyHookProcBase
     4     {
     5         protected IntPtr _nextHookPtr; //记录Hook编号
     6         protected CSharpHook.HookType hookType;
     7         protected int threadID;
     8         public void SetHook()
     9         {
    10             if (_nextHookPtr != IntPtr.Zero)
    11             {//已经勾过了
    12                 return;
    13             }
    14             //CSharpHook.HookProc myhookProc = new CSharpHook.HookProc(this.Proc); //声明一个自己的Hook实现函数的委托对象
    15 
    16             _nextHookPtr = CSharpHook.CSHook.SetWindowsHookEx((int)hookType, new CSharpHook.HookProc(this.Proc), IntPtr.Zero, this.threadID); //加到Hook链中
    17 
    18         }
    19 
    20         public void UnHook()
    21         {
    22 
    23             if (_nextHookPtr != IntPtr.Zero)
    24             {
    25 
    26                 CSharpHook.CSHook.UnhookWindowsHookEx(_nextHookPtr);//从Hook链中取消
    27                 _nextHookPtr = IntPtr.Zero;
    28             }
    29 
    30         }
    31         protected abstract IntPtr Proc(int code, IntPtr wparam, IntPtr lparam);
    32     }
    33 
    34 }

    上面是一个类库

    下面将创建一个Winform程序实现对本程序的键盘侦听

    下面是代码

    ----------------

    本程序具体的钩子业务逻辑

     1 namespace HookTool
     2 {
     3     public class MyHook : CSharpHook.MyHookProcBase
     4     {
     5         public int ThreadID
     6         {
     7             get {
     8                 return base.threadID;
     9             }
    10             set {
    11                 base.threadID = value;
    12             }
    13         } 
    14         public MyHook(CSharpHook.HookType ht) {
    15             base.hookType = ht;
    16         }
    17         public System.Windows.Forms.ListBox lbMsg;
    18         protected override IntPtr Proc(int code, IntPtr wparam, IntPtr lparam)
    19         {
    20             if (code < 0)
    21             {
    22                 return CSharpHook.CSHook.CallNextHookEx(this._nextHookPtr, code, wparam, lparam); //返回,让后面的程序处理该消息
    23             }
    24 
    25             if ((lparam.ToInt32() & 0x40000000)>0)
    26             {
    27                 //this.textBox1.Text = "a";
    28                 this.lbMsg.Items.Add((char)wparam.ToInt32());
    29                 return (IntPtr)1; //直接返回了,该消息就处理结束了
    30             }
    31             else
    32             {
    33                 return IntPtr.Zero; //返回,让后面的程序处理该消息
    34             }
    35         }
    36     }
    37 }

    Winform主程序

     1 namespace HookTool
     2 {
     3     public partial class Hook : Form
     4     {
     5         MyHook mh;
     6         public Hook()
     7         {
     8             InitializeComponent();
     9         }
    10 
    11         private void Hook_Load(object sender, EventArgs e)
    12         {
    13             mh=new MyHook(CSharpHook.HookType.Keyboard);
    14             this.lvProcess.Columns.AddRange(new ColumnHeader[]{
    15                 new ColumnHeader(){ Text="进程ID"},
    16                 new ColumnHeader(){ Text="进程名称"},
    17                 new ColumnHeader(){ Text="线程数"}
    18             });
    19             this.lvProcess.View = View.Details;
    20             GetProcess();
    21         }
    22 
    23         private void Hook_FormClosing(object sender, FormClosingEventArgs e)
    24         {
    25             mh.UnHook();
    26         }
    27 
    28         private void bMonitor_Click(object sender, EventArgs e)
    29         {
    30             mh.ThreadID = CSharpHook.CSHook.GetCurrentThreadId();
    31             mh.lbMsg = this.lbMsg;
    32             
    33             mh.SetHook();
    34         }
    35         void GetProcess() {
    36             this.lvProcess.Items.Clear();
    37             System.Diagnostics.Process[] ps=System.Diagnostics.Process.GetProcesses();
    38             foreach (System.Diagnostics.Process p in ps) {
    39                 this.lvProcess.Items.Add(new ListViewItem(new string[]{
    40                     p.Id.ToString(),
    41                     p.ProcessName,
    42                     p.Threads.Count.ToString()
    43                 }));
    44             }
    45         }
    46 
    47         private void bRefresh_Click(object sender, EventArgs e)
    48         {
    49             GetProcess();
    50         }
    51 
    52         private void bClose_Click(object sender, EventArgs e)
    53         {
    54             this.Close();
    55             System.Environment.Exit(0);
    56         }
    57     }
    58 }

    篇幅所限 不做详细说明

  • 相关阅读:
    SpringBoot + redis + @Cacheable注解实现缓存清除缓存
    Linux常用命令
    Java8 Stream分组
    VMware CentOS网络配置(局域网其它主机可访问Linux虚拟机)
    Jenkins实现自动打包,MAVEN打包,Shell脚本启动
    Docker常用命令,Docker安装Nginx、Redis、Jenkins、tomcat、MySQL
    Postman配置Pre-request scripts预请求对请求进行AES加密
    《Java并发编程的艺术》并发编程的基础(四)
    linux shell的创建与启动
    《Java并发编程的艺术》Java内存模型(三)
  • 原文地址:https://www.cnblogs.com/yomho/p/hook_net_Csharp.html
Copyright © 2020-2023  润新知