c#写钩子程序
你说的那个啥
wcHandle
压根就是一个窗口句柄
而SetWindowsHookEx
的第三个参数是
模块句柄
也就是说
你回调函数所在的模块的一个句柄
然后
最后一个参数是
进程id
和你需要进程绑定就可以了
局部钩子
没有写过
一般都写全局
HHOOK
SetWindowsHookEx( int
idHook,
//
钩子的类型,即它处理的消息类型 HOOKPROC
lpfn,
//
钩子子程的地址指针。如果dwThreadId参数为0 //
或是一个由别的进程创建的线程的标识, //
lpfn必须指向DLL中的钩子子程。 //
除此以外,lpfn可以指向当前进程的一段钩子子程代码。 // 钩子函数的入口地址,当钩子钩到任何消息后便调用这个函数。 HINSTANCE
hMod,
//
应用程序实例的句柄。标识包含lpfn所指的子程的 DLL。 //
如果dwThreadId
标识当前进程创建的一个线程, //
而且子程代码位于当前进程,hMod必须为NULL。 //
可以很简单的设定其为本应用程序的实例句柄。 DWORD
dwThreadId
//
与安装的钩子子程相关联的线程的标识符。 //
如果为0,钩子子程与所有的线程关联,即为全局钩子。 );
百科过来的
函数说明
C#是面向对象的编程语言,所以钩子是写在类中的。
/// /// 设置的钩子类型/// public enum HookType : int{ /// /// WH_MSGFILTER 和 WH_SYSMSGFILTER Hooks使我们可以把守菜单,迁移转变 ///条,消息框,对话框消息并且发明用户应用ALT+TAB or ALT+ESC 组合键切换窗口。 ///WH_MSGFILTER Hook只能把守传递到菜单,迁移转变条,消息框的消息,以及传递到通 ///过安装了Hook子过程的应用法度建树的对话框的消息。WH_SYSMSGFILTER Hook ///把守所有应用法度消息。 ///WH_MSGFILTER 和 WH_SYSMSGFILTER Hooks使我们可以在模式轮回时代 ///过滤消息,这等价于在主消息轮回中过滤消息。 ///经由过程调用CallMsgFilter function可以直接的调用WH_MSGFILTER Hook。经由过程应用这 ///个函数,应用法度可以或许在模式轮回时代应用雷同的代码去过滤消息,如同在主消息循 ///环里一样 /// WH_MSGFILTER = -1, /// /// WH_JOURNALRECORD Hook用来把守和记录输入事务。典范的,可以应用这 ///个Hook记录连气儿的鼠标和键盘事务,然后经由过程应用WH_JOURNALPLAYBACK Hook ///往返放。WH_JOURNALRECORD Hook是全局Hook,它不克不及象线程特定Hook一样 ///应用。WH_JOURNALRECORD是system-wide local hooks,它们不会被打针到任何行 ///程地址空间 /// WH_JOURNALRECORD = 0, /// /// WH_JOURNALPLAYBACK Hook使应用法度可以插入消息到体系消息队列。可 ///以应用这个Hook回放经由过程应用WH_JOURNALRECORD Hook记录下来的连气儿的鼠 ///标和键盘事务。只要WH_JOURNALPLAYBACK Hook已经安装,正常的鼠标和键盘 ///事务就是无效的。WH_JOURNALPLAYBACK Hook是全局Hook,它不克不及象线程特定 ///Hook一样应用。WH_JOURNALPLAYBACK Hook返回超时价,这个值告诉体系在处 ///理来自回放Hook当前消息之前须要守候多长时候(毫秒)。这就使Hook可以把握实 ///时事务的回放。WH_JOURNALPLAYBACK是system-wide local hooks,它们不会被 ///打针到任何行程地址空间 /// WH_JOURNALPLAYBACK = 1, /// /// 在应用法度中,WH_KEYBOARD Hook用来把守WM_KEYDOWN and ///WM_KEYUP消息,这些消息经由过程GetMessage or PeekMessage function返回。可以使 ///用这个Hook来把守输入到消息队列中的键盘消息 /// WH_KEYBOARD = 2, /// /// 应用法度应用WH_GETMESSAGE Hook来把守从GetMessage or PeekMessage函 ///数返回的消息。你可以应用WH_GETMESSAGE Hook去把守鼠标和键盘输入,以及 ///其它发送到消息队列中的消息 /// WH_GETMESSAGE = 3, /// /// 把守发送到窗口过程的消息,体系在消息发送到接管窗口过程之前调用 /// WH_CALLWNDPROC = 4, /// /// 在以下事务之前,体系都邑调用WH_CBT Hook子过程,这些事务包含: ///1. 激活,建树,烧毁,最小化,最大化,移动,改变尺寸等窗口事务; ///2. 完成体系指令; ///3. 来自体系消息队列中的移动鼠标,键盘事务; ///4. 设置输入核苦衷务; ///5. 同步体系消息队列事务。 ///Hook子过程的返回值断定体系是否容许或者防止这些操纵中的一个 /// WH_CBT = 5, /// /// WH_MSGFILTER 和 WH_SYSMSGFILTER Hooks使我们可以把守菜单,迁移转变 ///条,消息框,对话框消息并且发明用户应用ALT+TAB or ALT+ESC 组合键切换窗口。 ///WH_MSGFILTER Hook只能把守传递到菜单,迁移转变条,消息框的消息,以及传递到通 ///过安装了Hook子过程的应用法度建树的对话框的消息。WH_SYSMSGFILTER Hook ///把守所有应用法度消息。 ///WH_MSGFILTER 和 WH_SYSMSGFILTER Hooks使我们可以在模式轮回时代 ///过滤消息,这等价于在主消息轮回中过滤消息。 ///经由过程调用CallMsgFilter function可以直接的调用WH_MSGFILTER Hook。经由过程应用这 ///个函数,应用法度可以或许在模式轮回时代应用雷同的代码去过滤消息,如同在主消息循 ///环里一样 /// WH_SYSMSGFILTER = 6, /// /// WH_MOUSE Hook把守从GetMessage 或者 PeekMessage 函数返回的鼠标消息。 ///应用这个Hook把守输入到消息队列中的鼠标消息 /// WH_MOUSE = 7, /// /// 当调用GetMessage 或 PeekMessage 来从消息队列种查询非鼠标、键盘消息时 /// WH_HARDWARE = 8, /// /// 在体系调用体系中与其它Hook接洽关系的Hook子过程之前,体系会调用 ///WH_DEBUG Hook子过程。你可以应用这个Hook来决意是否容许体系调用与其它 ///Hook接洽关系的Hook子过程 /// WH_DEBUG = 9, /// /// 外壳应用法度可以应用WH_SHELL Hook去接管首要的通知。当外壳应用法度是 ///激活的并且当顶层窗口建树或者烧毁时,体系调用WH_SHELL Hook子过程。 ///WH_SHELL 共有5钟景象: ///1. 只要有个top-level、unowned 窗口被产生、起感化、或是被摧毁; ///2. 当Taskbar须要重画某个按钮; ///3. 当体系须要显示关于Taskbar的一个法度的最小化情势; ///4. 当今朝的键盘布局状况改变; ///5. 当应用者按Ctrl+Esc去履行Task Manager(或雷同级此外法度)。 ///遵守常规,外壳应用法度都不接管WH_SHELL消息。所以,在应用法度可以或许接 ///收WH_SHELL消息之前,应用法度必须调用SystemParametersInfo function注册它自 ///己 /// WH_SHELL = 10, /// /// 当应用法度的前台线程处于余暇状况时,可以应用WH_FOREGROUNDIDLE ///Hook履行低优先级的任务。当应用法度的前台线程可能要变成余暇状况时,体系就 ///会调用WH_FOREGROUNDIDLE Hook子过程 /// WH_FOREGROUNDIDLE = 11, /// /// 把守发送到窗口过程的消息,体系在消息发送到接管窗口过程之后调用 /// WH_CALLWNDPROCRET = 12, /// /// 把守输入到线程消息队列中的键盘消息 /// WH_KEYBOARD_LL = 13, /// /// 把守输入到线程消息队列中的鼠标消息 /// WH_MOUSE_LL = 14}public partial class Form1 : Form { public Form1() { InitializeComponent(); } [DllImport("USER32.DLL")]private static extern int CallNextHookEx(IntPtr hhk, int nCode, IntPtr wParam, IntPtr lParam);//导入钩子函数消息传递的方法[DllImport("USER32.DLL")]private static extern IntPtr SetWindowsHookEx(HookType idHook, HookProc lpfn, IntPtr hMod, int dwThreadId);//导入设置钩子的方法[DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]private static extern bool UnhookWindowsHookEx(int idHook); //导入卸载钩子的方法private delegate int HookProc(int nCode, int wParam, IntPtr lParam); //声明回调函数//////自定义回调函数///private int HookCallback(int nCode, IntPtr wParam, IntPtr lParam){ MessageBox.Show(nCode.ToString()); //键盘按下时 if (nCode >= 0 && wParam == (IntPtr)0) { int vkCode = Marshal.ReadInt32(lParam); Keys key = (Keys)vkCode; MessageBox.Show(key.ToString()); } return CallNextHookEx(handle, nCode, wParam, lParam);} private void Form1_Load(object sender, EventArgs e) { //创建钩子(这个函数的参数你可以百度找找,C#钩子研究过但没成功) SetWindowsHookEx(params); } }
一个程序的执行流程只是简单的演示下,如何实现一个HOOK在Net里面实现挂钩和在其他语言实现虽然在本质上是相同的,但细节上却是有点不同的
NET 采用的是事件驱动(消息机制的封装版),所有要实现一个消息的拦截,你必须实现
一个事件,而该事件的作用就是接受和处理
=======================================
1。开始我们定义一个基础类,实现一些基本的方法和变量
namespace Mr.Krcl.BaseHookLibrary
{
/*
hook library
by Mr.krcl 283018011
2010-5-12 BMD
: 这里给出的只是一个NET HOOK 模型 并未完全实现功能 */
// =================================================================
// 事件参数类
public class HookEventArgs: EventArgs
{
//根据需要你可以添加变量或函数实现功能的扩展
}
// ==================================================================
// 挂钩的消息类型,具体查阅MSDN
public enum HookType : int
{
WH_JOURNALRECORD = 0,
WH_JOURNALPLAYBACK = 1,
WH_KEYBOARD = 2,
WH_GETMESSAGE = 3,
WH_CALLWNDPROC = 4,
WH_CBT = 5,
WH_SYSMSGFILTER = 6,
WH_MOUSE = 7,
WH_HARDWARE = 8,
WH_DEBUG = 9,
WH_SHELL = 10,
WH_FOREGROUNDIDLE = 11,
WH_CALLWNDPROCRET = 12,
WH_KEYBOARD_LL = 13,
WH_MOUSE_LL = 14
}
// ====================================================================
// 导出API : 最烦人的工作了,不像C/C++其他语言直接调用头文件就OK
[DllImport("user32.dll")]
protected static extern IntPtr SetWindowsHookEx(HookType code,
HookProc func,
IntPtr hInstance,
int threadID);
[DllImport("user32.dll")]
protected static extern int UnhookWindowsHookEx(IntPtr hhook);
[DllImport("user32.dll")]
protected static extern int CallNextHookEx(IntPtr hhook,
int code, IntPtr wParam, IntPtr lParam);
// ====================================================================
// HOOK基类
public abstract class BaseHookLib:IDisposable{
// 事件委托 + 回调函数委托
public delegate CallBackHookProc(int nCode , IntPtr wparam ,IntPtr lparam) ;
public delegate HookEventHandler(object sender , HookEventArgs e);
public event HookEventHandler InvokeHook ;
// 构造函数
public BaseHookLib(HookType hType)
{
_hookType = hType ;
}
public BaseHookLib(HookType hType , CallBaseHookProc proc)
{
_hookType = hType ;
callBackFun = proc ;
}
// 内部变量
protected IntPtr _hhook = IntPtr.Zero;
// 判断系统是否已经加载HOOK
protected bool _isHook = false ;
// 回调函数
protected CallBackHookProc callBackFun ;
// 挂钩消息的类型
protected HookType _hookType ;
public bool IsHook{
get {
return _isHook;
}
}
// 引发时间
protected void OnHook(HookEventArgs e)
{
if(InvokeHook != null) InvokeHook(this , e);
}
// 钩子回调函数
protected int CallBackFunction(int nCode ,IntPtr wParam , IntPtr lparam)
{
if( nCode < 0) return CallNextHookEx(_hhook , nCode , wParam ,lparam);
// 事件参数类实例化
HookEventArgs e = new HookEventArgs(....) ;
OnHook(e) ;
// ...............
// 这里可以做你想做的,作为基类我们总是直接返回
// ................
return CallNextHookEx(_hhook,nCode ,wParam ,lparam);
}
// 安装钩子
protected void InstallHook()
{
_hhook = SetWindowsHookEx(_hookType ,callbackFun ,
Marshal.GetHINSTANCE(Assembly.GetExecutingAssembly().GetModules()[0]),,
0/*(int) AppDomain.GetCurrentThreadId()*/);
_hook = true ;
}
// 卸载钩子
protected void UnInstallHook()
{
UnhookWindowsHookEx(_hhook);
_hhook = IntPtr.Zero;
_hook = false ;
}
// =============================================================================
//
// 继承IDisposable接口的目的在于实现Dispose方法 ,该接口继承可在派生类中实现继承
//
// =============================================================================
}现在我们需要做的就是关键步骤的了实现一个鼠标的HOOK类,该类从BaseHookLib中派生
namespace Mr.Krcl.BaseHookLibrary
{
// 鼠标时间参数类
public class MouseHookEventArgs{
/*
这里你可以通过添加任何可用的成员变量或方法来实现该类的扩展
当然你也可以同对MouseEventArgs类的继承来扩展,例如:
public class MouseHookEventArgs : MouseEventArgs{
...
}
*/
}
// =================================================================================
// 定义鼠标时间委托
// 委托的形式是可变的,这里我们遵循原始的鼠标委托写法
// public delegate void MouseEventHandler(object sender ,MouseEventArgs e)
public delegate void MouseHookEventHandler(object sender,MouseHookEventArgs e);
// =================================================================================
// 主打类 MouseHookLib
// 因为我们要继承BaseHookLib所有我们这里就不需要在进程IDISxxx接口了
public class MouseHookLib
{
// 构造函数
// HOOK鼠标消息的类型由基类负责传递,利用C#构造函数层分布特点
public MouseHookLib():base(HookType.WH_MOUSE_LL){
callBackFun = new CallBackHookProc(MouseHookCallBackFunction);
}
public MouseHookLib():base(HookType.WH_MOUSE_LL,new CallBackHookProc(MouseHookCallBackFunction){
}
// 析构函数
// 作用通过调用重载的Dispose函数卸载钩钩
~MouseHookLib(){
Dispose(false);
}
// 实现Dispose方法
// 如果你在基类已经实现了改方法那么,这里你需要采用重载方式实现,或者直接基类该方法
// 这里假设积累没有实现该方法
protected void Dispose( bool disposing )
{
if ( IsInstalled )
Uninstall(); if ( disposing )
GC.SuppressFinalize( this );
}
public void Dispose()
{
Dispose( true );
}
/* 积累实现该方法后本类的重载实现
public override void Dispose( bool disposing )
{
if ( IsInstalled )
Uninstall(); if ( disposing )
GC.SuppressFinalize( this );
}
*/
// 事件
// 定义了时间和事件的触发方法
// 单独的定义事件是毫无意义的
// 这里我们以定义两个事件MouseDown ,MouseMove为例,具体根据自己的需要,方法是相同
public event MouseHookEventHander MouseMove ;
public void OnMouseMove(MouseHookEventArgs e)
{
if(MouseMove != null){
MouseMove(this , e);
}
}
public event MouseHookEventHander MouseDown ;
public void OnMouseMove(MouseHookEventArgs e)
{
if(MouseDown != null){
MouseDown(this , e);
}
}
// 鼠标钩子回调函数
public IntPtr MouseHookCallBackFunction(int nCode , IntPtr wParam , IntPtr lparam)
{
if( nCode < 0 ) return CallNextHookEx(_hhook , nCode ,wParam ,lParam);
MouseHookEventArgs e = new MouseHookEventArgs(.....) ;
/*
这里可以根据你自己的需要对拦截的消息进行过滤或者获取你自己需要的信息
例如:
if ( code == Win32.HC_ACTION ){
switch ( wParam.ToInt32() )
{
case Win32.WM_MOUSEMOVE:
OnMouseMove( e );
break;
case Win32.WM_LBUTTONDOWN:
case Win32.WM_RBUTTONDOWN:
case Win32.WM_MBUTTONDOWN:
case Win32.WM_XBUTTONDOWN:
OnMouseDown( e );
break;
}
}
这里只是一个模型 ,具体需要具体实现,关键就是根据lparam和wparam参数来实现事件的激活
从而调用事件,对目标消息进行拦截
*/
return CallNextHookEx(_hhook , nCode ,wParam ,lParam);
}
}
}
丁任丁疏: C#写HOOK还是延续WINDOWS HOOK的思路的,使用标准的API :SetWindowHookEx.... 思路很简单: 写个类自己定义一个钩子事件然后再自己程序中调用,下面是我以前写的一个NET HOOK框架,网上相关资源也是很多的 ===============...
天山区17761473009: c#求大神帮我写一段代码,关于全局键盘钩子的. - ?
丁任丁疏: http://keyboardmousehooks.codeplex.com/ 键盘鼠标HOOK..这个直接封装成库了,很不错,收藏着
天山区17761473009: 求c# 鼠标单击事件钩子代码 - ?
丁任丁疏: [DllImport("user32.dll")]static extern void mouse_event(MouseEventFlag flags, int dx, int dy, uint data, UIntPtr extraInfo); enum MouseEventFlag : uint{Move = 0x0001,LeftDown = 0x0002,LeftUp = 0x0004,RightDown = 0x0008,RightUp = 0x...
天山区17761473009: c#钩子是什么?书上没怎么说,求高手详细教教我. - ?
丁任丁疏: 钩子(Hook),是Windows消息处理机制的一个平台,应用程序可以在上面设置子程以监视指定窗口的某种消息,而且所监视的窗口可以是其他进程所创建的.当消息到达后,在目标窗口处理函数之前处理它.钩子机制允许应用程序截获处理window消息或特定事件.钩子实际上是一个处理消息的程序段,通过系统调用,把它挂入系统.每当特定的消息发出,在没有到达目的窗口前,钩子程序就先捕获该消息,亦即钩子函数先得到控制权.这时钩子函数即可以加工处理(改变)该消息,也可以不作处理而继续传递该消息,还可以强制结束消息的传递.给你个C#全局钩子参考代码: blog.csdn.net/speedupnow/article/details/6193882
天山区17761473009: C#钩子如何使用 - ?
丁任丁疏: 安装钩子: [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]private static extern IntPtr SetWindowsHookEx(int idHook, LowLevelKeyboardProc lpfn, IntPtr hMod, uint dwThreadId);调用API 具体参数可以百度,...
天山区17761473009: C#中的钩子,都有哪些??
丁任丁疏: 相信以前用过VB、Delphi,特别是VC的程序员应该对钩子程序都不陌生.在C#中我们同样可以使用钩子程序来实现特殊效果,比如当用户按下某个特殊键时提示,比如关闭应用程序前提示等. 当然使用方法相对VC来说要稍微复杂一点,有的地方还不太方便,下面的例子中实现两个基本功能: 1、按下Alt+F4时使窗口最小化 2、关闭应用程序前提示 这里有篇文章你可以去看看.. C#强化系列文章二:在C#中使用钩子http://www.cnblogs.com/firstyi/archive/2008/01/08/1030761.html
天山区17761473009: C# 可以设置线程钩子吗??
丁任丁疏: 可以,键盘钩子什么的都可以.
天山区17761473009: C#实现全局钩子的一点问题 - ?
丁任丁疏: protected static extern int SetWindowsHookEx(int idHook,HookProc lpfn,IntPtr hMod,int dwThreadId); protected 改成 public
天山区17761473009: 用C#做键盘敲击次数记录求代码 - ?
丁任丁疏: 刚好最近学习钩子,以下是整理源码. static int hKeyboardHook = 0; //键盘钩子句柄 public const int WH_KEYBOARD_LL = 13; //处理键盘消息 private const int WM_KEYDOWN = 0x100;//键盘按下 //声明键盘钩子事件类型. HookProc ...
天山区17761473009: C#求一个监控键盘鼠标响应的全局钩子?
丁任丁疏: using System.Runtime.InteropServices; #region 监视键盘和鼠标动作 [StructLayout(LayoutKind.Sequential)] struct LASTINPUTINFO { [MarshalAs(UnmanagedType.U4)] public int cbSize; [MarshalAs(UnmanagedType.U4)] public uint dwTime; } ...