回 帖 发 新 帖 刷新版面

主题:C#里能用钩子吗

C#里能用钩子吗 简介一下 谢!

回复列表 (共8个回复)

沙发

当然可以拉,用API就可以

板凳

能给我讲一下什么是“钩子”吗?

3 楼

钩子(Hook),是Windows消息处理机制的一个平台,应用程序可以在上面设置子程以监视指定窗口的某种消息,而且所监视的窗口可以是其他进程所创建的。当消息到达后,在目标窗口处理函数之前处理它。钩子机制允许应用程序截获处理window消息或特定事件。
钩子实际上是一个处理消息的程序段,通过系统调用,把它挂入系统。每当特定的消息发出,在没有到达目的窗口前,钩子程序就先捕获该消息,亦即钩子函数先得到控
制权。这时钩子函数即可以加工处理(改变)该消息,也可以不作处理而继续传递该消息,还可以强制结束消息的传递。

4 楼

请问上楼,如何编写钩子,能否举一例。谢。

5 楼

不过有个问题,除了键盘和鼠标可以全局HOOK以外,只能是本地HOOK,如果全局HOOK,会马上死机.这里需要注意.如果想其他的全局HOOK,只能用C++写.

6 楼

同意5楼的说法,msdn上面明确说明:
您无法在 Microsoft .NET 框架中实现全局挂钩。若要安装全局挂钩,挂钩必须有一个本机动态链接库 (DLL) 导出以便将其本身插入到另一个需要调入一个有效而且一致的函数的进程中。这需要一个 DLL 导出,而 .NET 框架不支持这一点。托管代码没有让函数指针具有统一的值这一概念,因为这些函数是动态构建的代理。
我给你贴一个C#中使用钩子函数的例子(来自Msdn),遇到不懂的就看Msdn,:)~~
using System.Runtime.InteropServices;
public delegate int HookProc(int nCode, IntPtr wParam, IntPtr lParam);
//定义钩子句柄
static int hHook = 0;
//定义钩子类型
public const int WH_MOUSE = 7;
//定义钩子处理函数
HookProc MouseHookProcedure;
[StructLayout(LayoutKind.Sequential)]
public class POINT
{
public int x;
public int y;
}
[StructLayout(LayoutKind.Sequential)]
public class MouseHookStruct
{
public POINT pt;
public int hwnd;
public int wHitTestCode;
public int dwExtraInfo;
}

//导入windows Api函数声明,这里要用到的函数有
//SetWindowsHookEx,UnhookWindowsHookEx,CallNextHookEx
[DllImport("user32.dll",CharSet=CharSet.Auto,
CallingConvention=CallingConvention.StdCall)]
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",CharSet=CharSet.Auto,
CallingConvention=CallingConvention.StdCall)]
public static extern int CallNextHookEx(int idHook, int nCode,
IntPtr wParam, IntPtr lParam);

//在Form中添加按钮Button,他的事件处理函数如下:
if(hHook == 0)
{
MouseHookProcedure = new HookProc(Form1.MouseHookProc);
//这里挂节钩子
hHook = SetWindowsHookEx(WH_MOUSE,
MouseHookProcedure,
(IntPtr)0,
AppDomain.GetCurrentThreadId());

if(hHook == 0 )
{
MessageBox.Show("SetWindowsHookEx Failed");
return;
}
button1.Text = "UnHook Windows Hook";
}
else
{
bool ret = UnhookWindowsHookEx(hHook);
if(ret == false )
{
MessageBox.Show("UnhookWindowsHookEx Failed");
return;
}
hHook = 0;
button1.Text = "Set Windows Hook";
this.Text = "Mouse Hook";
}

//完成钩子处理函数
public static int MouseHookProc(int nCode, IntPtr wParam, IntPtr lParam)
{
MouseHookStruct MyMouseHookStruct = (MouseHookStruct) Marshal.PtrToStructure(lParam, typeof(MouseHookStruct));

if (nCode < 0)
{
return CallNextHookEx(hHook, nCode, wParam, lParam);
}
else
{
String strCaption = "x = " +
MyMouseHookStruct.pt.x.ToString("d") +
"  y = " +
MyMouseHookStruct.pt.y.ToString("d");
Form tempForm = Form.ActiveForm;

tempForm.Text = strCaption;
return CallNextHookEx(hHook, nCode, wParam, lParam);
}
}
//程序运行后,当你单击Button会挂接钩子函数,当鼠标移动的时候会在Form.Text上
//面显示当前鼠标的位置,再次单击程序将释放钩子

7 楼

再罗嗦一下,//SetWindowsHookEx,UnhookWindowsHookEx,CallNextHookEx很重要的对于C#来说。一般的HOOK运用这些就可以.更深入的建议参看WINDOWS核心编程.

8 楼

[quote]同意5楼的说法,msdn上面明确说明:
您无法在 Microsoft .NET 框架中实现全局挂钩。若要安装全局挂钩,挂钩必须有一个本机动态链接库 (DLL) 导出以便将其本身插入到另一个需要调入一个有效而且一致的函数的进程中。这需要一个 DLL 导出,而 .NET 框架不支持这一点。托管代码没有让函数指针具有统一的值这一概念,因为这些函数是动态构建的代理。
我给你贴一个C#中使用钩子函数的例子(来自Msdn),遇到不懂的就看Msdn,:)~~
using System.Runtime.InteropServices;
public delegate int HookProc(int nCode, IntPtr wParam, IntPtr lParam);
//定义钩子句柄
static int hHook = 0;
//定义钩子类型
public const int WH_MOUSE = 7;
//定义钩子处理函数
HookProc MouseHookProcedure;
[StructLayout(LayoutKind.Sequential)]
public class POINT
{
public int x;
public int y;
}
[StructLayout(LayoutKind.Sequential)]
public class MouseHookStruct
{
public POINT pt;
public int hwnd;
public int wHitTestCode;
public int dwExtraInfo;
}

//导入windows Api函数声明,这里要用到的函数有
//SetWindowsHookEx,UnhookWindowsHookEx,CallNextHookEx
[DllImport("user32.dll",CharSet=CharSet.Auto,
CallingConvention=CallingConvention.StdCall)]
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",CharSet=CharSet.Auto,
CallingConvention=CallingConvention.StdCall)]
public static extern int CallNextHookEx(int idHook, int nCode,
IntPtr wParam, IntPtr lParam);

//在Form中添加按钮Button,他的事件处理函数如下:
if(hHook == 0)
{
MouseHookProcedure = new HookProc(Form1.MouseHookProc);
//这里挂节钩子
hHook = SetWindowsHookEx(WH_MOUSE,
MouseHookProcedure,
(IntPtr)0,
AppDomain.GetCurrentThreadId());

if(hHook == 0 )
{
MessageBox.Show("SetWindowsHookEx Failed");
return;
}
button1.Text = "UnHook Windows Hook";
}
else
{
bool ret = UnhookWindowsHookEx(hHook);
if(ret == false )
{
MessageBox.Show("UnhookWindowsHookEx Failed");
return;
}
hHook = 0;
button1.Text = "Set Windows Hook";
this.Text = "Mouse Hook";
}

//完成钩子处理函数
public static int MouseHookProc(int nCode, IntPtr wParam, IntPtr lParam)
{
MouseHookStruct MyMouseHookStruct = (MouseHookStruct) Marshal.PtrToStructure(lParam, typeof(MouseHookStruct));

if (nCode < 0)
{
return CallNextHookEx(hHook, nCode, wParam, lParam);
}
else
{
String strCaption = "x = " +
MyMouseHookStruct.pt.x.ToString("d") +
"&nbsp;&nbsp;y = " +
MyMouseHookStruct.pt.y.ToString("d");
Form tempForm = Form.ActiveForm;

tempForm.Text = strCaption;
return CallNextHookEx(hHook, nCode, wParam, lParam);
}
}
//程序运行后,当你单击Button会挂接钩子函数,当鼠标移动的时候会在Form.Text上
//面显示当前鼠标的位置,再次单击程序将释放钩子[/quote]

我来回复

您尚未登录,请登录后再回复。点此登录或注册