.NET的键盘Hook管理类,用于禁用键盘输入和切换
- 手机
- 2025-08-18 11:57:02

一、MyHook帮助类
此类需要编写指定屏蔽的按键,灵活性差。
using System; using System.Runtime.InteropServices; using System.Diagnostics; using System.Windows.Forms; using Microsoft.Win32; namespace MyHookClass { /// <summary> /// 类一 /// </summary> public class MyHook { //消息函数的委托 public delegate int HookProc(int nCode, int wParam, IntPtr lParam); static int hHook = 0; public const int WH_KEYBOARD_LL = 13;//底层键盘钩子 static HookProc KeyBoardHookProcedure; //按键信息结构 [StructLayout(LayoutKind.Sequential)] public class KeyBoardHookStruct { public int vkCode; public int scanCode; public int flags; public int time; public int dwExtraInfo; } //安装钩子 [DllImport("user32.dll")] public static extern int SetWindowsHookEx(int idHook, HookProc lpfn, IntPtr hInstance, int threadId); //卸载钩子 [DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)] public static extern bool UnhookWindowsHookEx(int idHook); //下一个钩挂的函数 [DllImport("user32.dll")] public static extern int CallNextHookEx(int idHook, int nCode, int wParam, IntPtr lParam); //返回当前线程 ID [DllImport("kernel32.dll")] public static extern int GetCurrentThreadId(); //得到模块的句柄 [DllImport("kernel32.dll")] public static extern IntPtr GetModuleHandle(string name); //安装钩子 public static void InsertHook() { if (hHook == 0) { KeyBoardHookProcedure = new HookProc(KeyBoardHookProc); hHook = SetWindowsHookEx(WH_KEYBOARD_LL, KeyBoardHookProcedure, GetModuleHandle(Process.GetCurrentProcess().MainModule.ModuleName), 0); if (hHook == 0) { UnHook(); throw new Exception("设置Hook失败!"); } else { RegistryKey key = Registry.CurrentUser.OpenSubKey(@"Software\Microsoft\Windows\CurrentVersion\Policies\System", true); if (key == null)//如果该项不存在的话,则创建该项 key = Registry.CurrentUser.CreateSubKey(@"Software\Microsoft\Windows\CurrentVersion\Policies\System"); key.SetValue("DisableTaskMgr", 1, RegistryValueKind.DWord); //key.SetValue("DisableLockWorkstation", 1, RegistryValueKind.DWord); key.Close(); } } } //卸载钩子 public static void UnHook() { bool retKeyboard = true; if (hHook != 0) { retKeyboard = UnhookWindowsHookEx(hHook); hHook = 0; } //if (!retKeyboard) throw new Exception("卸载Hook失败!"); RegistryKey key = Registry.CurrentUser.OpenSubKey(@"Software\Microsoft\Windows\CurrentVersion\Policies\System", true); if (key != null) { key.DeleteValue("DisableTaskMgr", false); //key.DeleteValue("DisableLockWorkstation", false); key.Close(); } } //按键消息的处理函数 public static int KeyBoardHookProc(int nCode, int wParam, IntPtr lParam) { if (nCode >= 0) { KeyBoardHookStruct kbh = (KeyBoardHookStruct)Marshal.PtrToStructure(lParam, typeof(KeyBoardHookStruct)); //添加自己的判断语句,如果符合要求的按键,就 return 1; //没有判断直接 return 1;那么就屏蔽所有按键除了ctrl+alt+del //屏蔽Ctrl+Esc if (kbh.vkCode == (int)Keys.Delete && (int)Control.ModifierKeys == (int)Keys.Control + (int)Keys.Alt) //截获Ctrl+Alt+Delete { PubLibrary.WriteErrLog("1.拦截信息:Ctrl+Alt+Delete"); return 1; } if (kbh.vkCode == (int)Keys.Escape) { PubLibrary.WriteErrLog("2.拦截信息:Escape"); return 1; } if (kbh.vkCode == 91) // 截获左win(开始菜单键) { PubLibrary.WriteErrLog("3.拦截信息:截获左win"); return 1; } if (kbh.vkCode == 92)// 截获右win { PubLibrary.WriteErrLog("4.拦截信息:截获右win"); return 1; } //if (kbh.vkCode == (int)Keys.L) //{ // PubLibrary.WriteErrLog("5.拦截信息:L"); // return 1; //} if (kbh.vkCode == (int)Keys.Alt) { PubLibrary.WriteErrLog("6.拦截信息:Alt"); return 1; } if ((int)Control.ModifierKeys == (int)Keys.Alt) //截获alt { PubLibrary.WriteErrLog("7.拦截信息:Alt"); return 1; } if (kbh.vkCode == (int)Keys.Escape && (int)Control.ModifierKeys == (int)Keys.Control) //截获Ctrl+Esc { PubLibrary.WriteErrLog("8.拦截信息:Ctrl+Esc"); return 1; } if (kbh.vkCode == (int)Keys.Escape && (int)Control.ModifierKeys == (int)Keys.Alt) //截获Alt+Esc { PubLibrary.WriteErrLog("9.拦截信息:Alt+Esc"); return 1; } if (kbh.vkCode == (int)Keys.F4 && (int)Control.ModifierKeys == (int)Keys.Alt) //截获alt+f4 { PubLibrary.WriteErrLog("10.拦截信息:F4+Alt"); return 1; } if (kbh.vkCode == (int)Keys.Tab && (int)Control.ModifierKeys == (int)Keys.Alt) //截获alt+tab { PubLibrary.WriteErrLog("10.拦截信息:alt+tab"); return 1; } if (kbh.vkCode == (int)Keys.Escape && (int)Control.ModifierKeys == (int)Keys.Control + (int)Keys.Shift) //截获Ctrl+Shift+Esc { PubLibrary.WriteErrLog("11.拦截信息:Ctrl+Shift+Esc"); return 1; } if (kbh.vkCode == (int)Keys.Space && (int)Control.ModifierKeys == (int)Keys.Alt) //截获alt+空格 { PubLibrary.WriteErrLog("12.拦截信息:alt+空格"); return 1; } if (kbh.vkCode == 241) //截获F1 { PubLibrary.WriteErrLog("13.拦截信息:F1"); return 1; } if ((int)Control.ModifierKeys == (int)Keys.Control + (int)Keys.Alt + (int)Keys.Delete) //截获Ctrl+Alt+Delete { PubLibrary.WriteErrLog("14.拦截信息:Ctrl+Alt+Delete"); return 1; } if ((int)Control.ModifierKeys == (int)Keys.Control + (int)Keys.Shift) //截获Ctrl+Shift { PubLibrary.WriteErrLog("15.拦截信息:Ctrl+Shift"); return 1; } if (kbh.vkCode == (int)Keys.Space && (int)Control.ModifierKeys == (int)Keys.Control + (int)Keys.Alt) //截获Ctrl+Alt+空格 { PubLibrary.WriteErrLog("16.拦截信息:Ctrl+Alt+空格"); return 1; } } return CallNextHookEx(hHook, nCode, wParam, lParam); } } }二、KeyboardHookLib帮助类
using System; using System.Runtime.InteropServices; using System.Diagnostics; using Microsoft.Win32; namespace VendorSoftwareReleaseLW.Class { /// <summary> /// 键盘Hook管理类 /// </summary> public class KeyboardHookLib { private const int WH_KEYBOARD_LL = 13; //键盘 //键盘处理事件委托 ,当捕获键盘输入时调用定义该委托的方法. private delegate int HookHandle(int nCode, int wParam, IntPtr lParam); //客户端键盘处理事件 public delegate void ProcessKeyHandle(HookStruct param, out bool handle); //接收SetWindowsHookEx返回值 private static int _hHookValue = 0; //勾子程序处理事件 private HookHandle _KeyBoardHookProcedure; //Hook结构 [StructLayout(LayoutKind.Sequential)] public class HookStruct { public int vkCode; public int scanCode; public int flags; public int time; public int dwExtraInfo; } //设置钩子 [DllImport("user32.dll")] private static extern int SetWindowsHookEx(int idHook, HookHandle lpfn, IntPtr hInstance, int threadId); //取消钩子 [DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)] private static extern bool UnhookWindowsHookEx(int idHook); //调用下一个钩子 [DllImport("user32.dll")] private static extern int CallNextHookEx(int idHook, int nCode, int wParam, IntPtr lParam); //获取当前线程ID [DllImport("kernel32.dll")] private static extern int GetCurrentThreadId(); //Gets the main module for the associated process. [DllImport("kernel32.dll")] private static extern IntPtr GetModuleHandle(string name); private IntPtr _hookWindowPtr = IntPtr.Zero; //构造器 public KeyboardHookLib() { } //外部调用的键盘处理事件 private static ProcessKeyHandle _clientMethod = null; /// <summary> /// 安装勾子 /// </summary> /// <param name="hookProcess">外部调用的键盘处理事件</param> public void InstallHook(ProcessKeyHandle clientMethod) { _clientMethod = clientMethod; // 安装键盘钩子 if (_hHookValue == 0) { _KeyBoardHookProcedure = new HookHandle(OnHookProc); _hookWindowPtr = GetModuleHandle(Process.GetCurrentProcess().MainModule.ModuleName); //************************************ //键盘线程钩子 //SetWindowsHookEx( 2,KeyboardHookProcedure, IntPtr.Zero, GetCurrentThreadId()); //GetCurrentThreadId()为要监视的线程ID,你完全可以自己写个方法获取QQ的线程哦 //键盘全局钩子,需要引用空间(using System.Reflection;) //SetWindowsHookEx( 13,KeyboardHookProcedure,Marshal.GetHINSTANCE(Assembly.GetExecutingAssembly().GetModules()[0]),0); // //关于SetWindowsHookEx (int idHook, HookProc lpfn, IntPtr hInstance, int threadId)函数将钩子加入到钩子链表中,说明一下四个参数: //idHook 钩子类型,即确定钩子监听何种消息,上面的代码中设为2,即监听键盘消息并且是线程钩子,如果是全局钩子监听键盘消息应设为13, //线程钩子监听鼠标消息设为7,全局钩子监听鼠标消息设为14。 // //lpfn 钩子子程的地址指针。如果dwThreadId参数为0 或是一个由别的进程创建的线程的标识,lpfn必须指向DLL中的钩子子程。 除此以外,lpfn可 //以指向当前进程的一段钩子子程代码。钩子函数的入口地址,当钩子钩到任何消息后便调用这个函数。 // //hInstance应用程序实例的句柄。标识包含lpfn所指的子程的DLL。如果threadId 标识当前进程创建的一个线程,而且子程代码位于当前 //进程,hInstance必须为NULL。可以很简单的设定其为本应用程序的实例句柄。 // //threadedId 与安装的钩子子程相关联的线程的标识符。如果为0,钩子子程与所有的线程关联,即为全局钩子。 //************************************ _hHookValue = SetWindowsHookEx( WH_KEYBOARD_LL, _KeyBoardHookProcedure, _hookWindowPtr, 0); //如果设置钩子失败. if (_hHookValue == 0) { UninstallHook(); } else { RegistryKey key = Registry.CurrentUser.OpenSubKey(@"Software\Microsoft\Windows\CurrentVersion\Policies\System", true); if (key == null)//如果该项不存在的话,则创建该项 key = Registry.CurrentUser.CreateSubKey(@"Software\Microsoft\Windows\CurrentVersion\Policies\System"); key.SetValue("DisableTaskMgr", 1, RegistryValueKind.DWord); //key.SetValue("DisableLockWorkstation", 1, RegistryValueKind.DWord); key.Close(); } } } //取消钩子事件 public void UninstallHook() { if (_hHookValue != 0) { bool ret = UnhookWindowsHookEx(_hHookValue); if (ret) _hHookValue = 0; } RegistryKey key = Registry.CurrentUser.OpenSubKey(@"Software\Microsoft\Windows\CurrentVersion\Policies\System", true); if (key != null) { key.DeleteValue("DisableTaskMgr", false); //key.DeleteValue("DisableLockWorkstation", false); key.Close(); } } //钩子事件内部调用,调用_clientMethod方法转发到客户端应用。 private static int OnHookProc(int nCode, int wParam, IntPtr lParam) { if (nCode >= 0) { //转换结构 HookStruct hookStruct = (HookStruct)Marshal.PtrToStructure(lParam, typeof(HookStruct)); if (_clientMethod != null) { bool handle = false; //调用客户提供的事件处理程序。 _clientMethod(hookStruct, out handle); if (handle) return 1; //1:表示拦截键盘,return 退出 } } return CallNextHookEx(_hHookValue, nCode, wParam, lParam); } } }三、在WinForm中的使用
using Newtonsoft.Json; using System; using System.Collections.Generic; using System.Data; using System.Diagnostics; using System.Runtime.InteropServices; using System.Threading; using System.Windows.Forms; using MyHookClass; using KeyboardHookLibClass; namespace TestForm { public partial class LoginForm : Form { DateTime _dtNow; [DllImport("user32.dll")] private static extern IntPtr GetForegroundWindow(); [DllImport("user32.dll")] private static extern bool SetForegroundWindow(IntPtr hWnd); [DllImport("user32.dll")] private static extern IntPtr FindWindow(string lpClassName, string lpWindowName); [DllImport("user32.dll")] public static extern bool SetWindowPos(IntPtr hWnd, int hWndInsertAfter, int X, int Y, int cx, int cy, int uFlags); [DllImport("user32.dll")] public static extern bool IsWindowVisible(IntPtr hWnd); //勾子管理类 private KeyboardHookLib _keyboardHook = null; public delegate void ForegroundWin(); private void LoginForm_Load(object sender, EventArgs e) { SetHook(); Thread threadForeground = new Thread(ShowWindowAsync); //threadForeground.IsBackground = true; threadForeground.Start(); } private void txt_KeyDown(object sender, KeyEventArgs e) { _dtNow = DateTime.Now; } private void txt_KeyUp(object sender, KeyEventArgs e) { if (e.KeyCode != Keys.Enter) { DateTime dtTemp = DateTime.Now; TimeSpan ts = dtTemp.Subtract(_dtNow); if (ts.Milliseconds > 65) { //setTool("错误:禁止手工输入!", "N"); txt.Text = "";//清空 } } } private void txtID_KeyPress(object sender, KeyPressEventArgs e) { if (e.KeyChar == 13) { //做些操作 ClearHook(); } } public static void SetWindowPos(IntPtr hWnd) { //0x0010为不激活窗口,这个比较关键 SetWindowPos(hWnd, -1, 0, 0, 0, 0, 0x0001 | 0x0002 | 0x0010);// 0x001 | 0x002 | 0x0010| 0x040 } private void ShowWindowAsync() { while (true) { //高版本的这里可以直接使用Action,更简化一些 //ForegroundWin d = new ForegroundWin(action); //this.Invoke(d); Action a = new Action(() => { action(); }); Thread.Sleep(100);//这个时间间隔,用户基本感觉不出有切换窗体 } } void action() { IntPtr hWnd = this.Handle; if (hWnd != IntPtr.Zero || GetForegroundWindow() != hWnd) { //选中当前的句柄窗口 SetWindowPos(hWnd); //SendKeys.SendWait(" "); } } private void ClearHook() { //取消勾子 if (_keyboardHook != null) _keyboardHook.UninstallHook(); //MyHook.UnHook(); //ProcessMgr.ResumeWinlogon(); } private void SetHook() { //安装勾子 _keyboardHook = new KeyboardHookLib(); _keyboardHook.InstallHook(this.OnKeyPress); //MyHook.InsertHook(); //ProcessMgr.SuspendWinlogon(); } /// <summary> /// 客户端键盘捕捉事件. /// </summary> /// <param name="hookStruct">由Hook程序发送的按键信息</param> /// <param name="handle">是否拦截</param> public void OnKeyPress(KeyboardHookLib.HookStruct hookStruct, out bool handle) { handle = false; //预设不拦截任何键 if (hookStruct.vkCode == 91) // 截获左win(开始菜单键) { handle = true; } if (hookStruct.vkCode == 92)// 截获右win { handle = true; } if ((int)Control.ModifierKeys == (int)Keys.Alt) //截获alt { handle = true; } //截获Ctrl+Esc if (hookStruct.vkCode == (int)Keys.Escape && (int)Control.ModifierKeys == (int)Keys.Control) { handle = true; } //截获alt+f4 if (hookStruct.vkCode == (int)Keys.F4 && (int)Control.ModifierKeys == (int)Keys.Alt) { handle = true; } //截获alt+tab if (hookStruct.vkCode == (int)Keys.Tab && (int)Control.ModifierKeys == (int)Keys.Alt) { handle = true; } //截获alt+tab if (hookStruct.vkCode == (int)Keys.Escape && (int)Control.ModifierKeys == (int)Keys.Alt) { handle = true; } //截获F1 if (hookStruct.vkCode == (int)Keys.F1) { handle = true; } //截获Ctrl+Alt+Delete if ((int)Control.ModifierKeys == (int)Keys.Control + (int)Keys.Alt + (int)Keys.Delete) { handle = true; } //如果键A~Z if (hookStruct.vkCode >= (int)Keys.A && hookStruct.vkCode <= (int)Keys.Z) { //挡掉B键 if (hookStruct.vkCode == (int)Keys.B) hookStruct.vkCode = (int)Keys.None; //设键为0 handle = true; } Keys key = (Keys)hookStruct.vkCode; PubLibrary.WriteErrLog("你按下:" + (key == Keys.None ? "" : key.ToString())); } } }四、其他类
using System; using System.Runtime.InteropServices; namespace ShareToolClass { public class ShareTool : IDisposable { [DllImport("advapi32.dll", SetLastError = true)] static extern bool LogonUser(string pszUsername, string pszDomain, string pszPassword, int dwLogonType, int dwLogonProvider, ref IntPtr phToken); // closes open handes returned by LogonUser [DllImport("kernel32.dll", CharSet = CharSet.Auto)] extern static bool CloseHandle(IntPtr handle); [DllImport("Advapi32.DLL")] static extern bool ImpersonateLoggedOnUser(IntPtr hToken); [DllImport("Advapi32.DLL")] static extern bool RevertToSelf(); const int LOGON32_PROVIDER_DEFAULT = 0; const int LOGON32_LOGON_NEWCREDENTIALS = 9; const int LOGON32_LOGON_INTERACTIVE = 2; private bool disposed; public ShareTool(string username, string password, string ip) { // initialize tokens IntPtr pExistingTokenHandle = new IntPtr(0); IntPtr pDuplicateTokenHandle = new IntPtr(0); try { // get handle to token bool bImpersonated = LogonUser(username, ip, password, LOGON32_LOGON_NEWCREDENTIALS, LOGON32_PROVIDER_DEFAULT, ref pExistingTokenHandle); if (bImpersonated) { if (!ImpersonateLoggedOnUser(pExistingTokenHandle)) { int nErrorCode = Marshal.GetLastWin32Error(); throw new Exception("ImpersonateLoggedOnUser error;Code=" + nErrorCode); } } else { int nErrorCode = Marshal.GetLastWin32Error(); throw new Exception("LogonUser error;Code=" + nErrorCode); } } finally { // close handle(s) if (pExistingTokenHandle != IntPtr.Zero) CloseHandle(pExistingTokenHandle); if (pDuplicateTokenHandle != IntPtr.Zero) CloseHandle(pDuplicateTokenHandle); } } protected virtual void Dispose(bool disposing) { if (!disposed) { RevertToSelf(); disposed = true; } } public void Dispose() { Dispose(true); } } } using System; using System.Diagnostics; using System.Runtime.InteropServices; namespace ProcessMgrClass { class ProcessMgr { /// <summary> /// The process-specific access rights. /// </summary> [Flags] public enum ProcessAccess : uint { /// <summary> /// Required to terminate a process using TerminateProcess. /// </summary> Terminate = 0x1, /// <summary> /// Required to create a thread. /// </summary> CreateThread = 0x2, /// <summary> /// Undocumented. /// </summary> SetSessionId = 0x4, /// <summary> /// Required to perform an operation on the address space of a process (see VirtualProtectEx and WriteProcessMemory). /// </summary> VmOperation = 0x8, /// <summary> /// Required to read memory in a process using ReadProcessMemory. /// </summary> VmRead = 0x10, /// <summary> /// Required to write to memory in a process using WriteProcessMemory. /// </summary> VmWrite = 0x20, /// <summary> /// Required to duplicate a handle using DuplicateHandle. /// </summary> DupHandle = 0x40, /// <summary> /// Required to create a process. /// </summary> CreateProcess = 0x80, /// <summary> /// Required to set memory limits using SetProcessWorkingSetSize. /// </summary> SetQuota = 0x100, /// <summary> /// Required to set certain information about a process, such as its priority class (see SetPriorityClass). /// </summary> SetInformation = 0x200, /// <summary> /// Required to retrieve certain information about a process, such as its token, exit code, and priority class (see OpenProcessToken, GetExitCodeProcess, GetPriorityClass, and IsProcessInJob). /// </summary> QueryInformation = 0x400, /// <summary> /// Undocumented. /// </summary> SetPort = 0x800, /// <summary> /// Required to suspend or resume a process. /// </summary> SuspendResume = 0x800, /// <summary> /// Required to retrieve certain information about a process (see QueryFullProcessImageName). A handle that has the PROCESS_QUERY_INFORMATION access right is automatically granted PROCESS_QUERY_LIMITED_INFORMATION. /// </summary> QueryLimitedInformation = 0x1000, /// <summary> /// Required to wait for the process to terminate using the wait functions. /// </summary> Synchronize = 0x100000 } [DllImport("ntdll.dll")] private static extern uint NtResumeProcess([In] IntPtr processHandle); [DllImport("ntdll.dll")] private static extern uint NtSuspendProcess([In] IntPtr processHandle); [DllImport("kernel32.dll", SetLastError = true)] private static extern IntPtr OpenProcess( ProcessAccess desiredAccess, bool inheritHandle, int processId); [DllImport("kernel32.dll", SetLastError = true)] [return: MarshalAs(UnmanagedType.Bool)] private static extern bool CloseHandle([In] IntPtr handle); public static void SuspendProcess(int processId) { IntPtr hProc = IntPtr.Zero; try { // Gets the handle to the Process hProc = OpenProcess(ProcessAccess.SuspendResume, false, processId); if (hProc != IntPtr.Zero) NtSuspendProcess(hProc); } finally { // Don't forget to close handle you created. if (hProc != IntPtr.Zero) CloseHandle(hProc); } } public static void ResumeProcess(int processId) { IntPtr hProc = IntPtr.Zero; try { // Gets the handle to the Process hProc = OpenProcess(ProcessAccess.SuspendResume, false, processId); if (hProc != IntPtr.Zero) NtResumeProcess(hProc); } finally { // Don't forget to close handle you created. if (hProc != IntPtr.Zero) CloseHandle(hProc); } } public static void SuspendWinlogon() { Process[] processes = Process.GetProcesses(); foreach (Process process in processes) { if (process.ProcessName == "winlogon") { SuspendProcess(process.Id); } } } public static void ResumeWinlogon() { Process[] processes = Process.GetProcesses(); foreach (Process process in processes) { Console.WriteLine(process.ProcessName); if (process.ProcessName == "winlogon") { ResumeProcess(process.Id); } } } } }.NET的键盘Hook管理类,用于禁用键盘输入和切换由讯客互联手机栏目发布,感谢您对讯客互联的认可,以及对我们原创作品以及文章的青睐,非常欢迎各位朋友分享到个人网站或者朋友圈,但转载请说明文章出处“.NET的键盘Hook管理类,用于禁用键盘输入和切换”