一、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);
}
}
}
}
}