利用HOOK技术来做一个键盘记录器,看看一天下来,我们点击了多少次键盘,哪些键的使用频率最高。
实现功能:
使用C#实现一个键盘记录器
开发环境:
开发工具: Visual Studio 2013
.NET Framework版本:4.5
实现代码:
public class HookUtil{#region windows api/// <summary>/// 安装钩子/// </summary>[DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]public static extern int SetWindowsHookEx(int idHook, HookProc lpfn, IntPtr hInstance, int threadId);public delegate int HookProc(int nCode, Int32 wParam, IntPtr lParam);/// <summary>/// 继续下一个钩子/// </summary>[DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]public static extern int CallNextHookEx(int idHook, int nCode, Int32 wParam, IntPtr lParam);/// <summary>/// 卸载钩子/// </summary>[DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]public static extern bool UnhookWindowsHookEx(int idHook);/// <summary>///获取当前线程编号(线程钩子需要用到)[DllImport("kernel32.dll")]static extern int GetCurrentThreadId();/// <summary>/// 获取当前实例的函数/// </summary>[DllImport("kernel32.dll")]public static extern IntPtr GetModuleHandle(string name);/// <summary>/// 获取按键的状态/// </summary>/// <param name="pbKeyState"></param>/// <returns></returns>[DllImport("user32")]public static extern int GetKeyboardState(byte[] pbKeyState);/// <summary>/// 将指定的虚拟键码和键盘状态翻译为相应的字符或字符串/// </summary>[DllImport("user32")]public static extern int ToAscii(int uVirtKey, int uScanCode, byte[] lpbKeyState,byte[] lpwTransKey,int fuState); #endregion/// <summary>/// 键盘结构/// </summary>[StructLayout(LayoutKind.Sequential)]public class KeyboardHookStruct{public int vkCode; //定一个虚拟键码。该代码必须有一个价值的范围1至254public int scanCode; // 指定的硬件扫描码的关键public int flags; // 键标志public int time; // 指定的时间戳记的这个讯息public int dwExtraInfo; // 指定额外信息相关的信息}//定义为键盘钩子public int WH_KEYBOARD_LL = 13;//相关键盘事件public event KeyEventHandler KeyDownEvent;public event KeyPressEventHandler KeyPressEvent;public event KeyEventHandler KeyUpEvent;//相关动作private const int WM_KEYDOWN = 0x100;//KEYDOWNprivate const int WM_KEYUP = 0x101;//KEYUPprivate const int WM_SYSKEYDOWN = 0x104;//SYSKEYDOWNprivate const int WM_SYSKEYUP = 0x105;//SYSKEYUP//hookidprivate int hookID = 0;//向下传递数据public Keys NoNextKeyCode;/// <summary>/// 安装钩子/// </summary>public void StartHook(){if (hookID == 0){HookProc hookProc = new HookProc(KeyboardHookProc);hookID = SetWindowsHookEx(WH_KEYBOARD_LL, hookProc, GetModuleHandle(System.Diagnostics.Process.GetCurrentProcess().MainModule.ModuleName), 0);if (hookID == 0){StopHook();throw new Exception("安装键盘钩子失败");}}}public void StopHook(){bool isStop = true;if (hookID != 0){isStop = UnhookWindowsHookEx(hookID);hookID = 0;}if (!isStop) throw new Exception("卸载键盘钩子失败!");}/// <summary>/// 监听事件/// </summary>private int KeyboardHookProc(int nCode, Int32 wParam, IntPtr lParam){if ((nCode >= 0) && (KeyDownEvent != null || KeyUpEvent != null || KeyPressEvent != null)){KeyboardHookStruct MyKeyboardHookStruct = (KeyboardHookStruct)Marshal.PtrToStructure(lParam, typeof(KeyboardHookStruct));//按下处理if (KeyDownEvent != null && (wParam == WM_KEYDOWN || wParam == WM_SYSKEYDOWN)){Keys keyData = (Keys)MyKeyboardHookStruct.vkCode;KeyEventArgs e = new KeyEventArgs(keyData);KeyDownEvent(this, e);//阻止向下传递if (NoNextKeyCode == keyData){return hookID;}}//按下并抬起处理if (KeyPressEvent != null && wParam == WM_KEYDOWN){byte[] keyState = new byte[256];GetKeyboardState(keyState);byte[] inBuffer = new byte[2];if (ToAscii(MyKeyboardHookStruct.vkCode, MyKeyboardHookStruct.scanCode, keyState, inBuffer, MyKeyboardHookStruct.flags) == 1){KeyPressEventArgs e = new KeyPressEventArgs((char)inBuffer[0]);KeyPressEvent(this, e);}}// 抬起处理if (KeyUpEvent != null && (wParam == WM_KEYUP || wParam == WM_SYSKEYUP)){Keys keyData = (Keys)MyKeyboardHookStruct.vkCode;KeyEventArgs e = new KeyEventArgs(keyData);KeyUpEvent(this, e);}}return CallNextHookEx(hookID, nCode, wParam, lParam);}~HookUtil(){StopHook();}}
HookUtil keyHook = new HookUtil();private void btnBegin_Click(object sender, EventArgs e){keyHook.KeyDownEvent += new KeyEventHandler(hook_KeyDown);//钩住按下事件keyHook.StartHook();btnBegin.Enabled = false;btnEnd.Enabled = true;}private void btnEnd_Click(object sender, EventArgs e){keyHook.StopHook();btnBegin.Enabled = true;btnEnd.Enabled = false;}private void btnInfo_Click(object sender, EventArgs e){string path = System.AppDomain.CurrentDomain.BaseDirectory + "log\\" + DateTime.Now.ToString("yyyy-MM-dd") + ".txt";if (!File.Exists(path)){MessageBox.Show("还未监听到数据,请操作后再查看");return;}var list = File.ReadAllLines(path).ToList().GroupBy(s => s).Select(s => new { s.Key, s.ToList().Count }).OrderByDescending(s => s.Count);FrmInfo frm = new FrmInfo();frm.Show();foreach (var item in list){frm.addItems(new string[] { "", item.Key, item.Count + "" });}}private void hook_KeyDown(object sender, KeyEventArgs e){if (!listKey.Contains(e.KeyData)){if (Control.ModifierKeys != Keys.None){WriteLog(Control.ModifierKeys + "+" + e.KeyData);}else{WriteLog(e.KeyData + "");}}else{WriteLog(e.KeyData + "");}}
实现效果:
由简入繁,拿来即用
更多精彩,请搜索公众号:Csharp 小记