base64位编码:C#系统钩子的实现

来源:百度文库 编辑:偶看新闻 时间:2024/04/24 09:24:21

C#系统钩子的实现  

2011-04-23 10:40:37|  分类: c#——qq |字号 订阅

看了很多资料,都提到系统钩子(Hook)必须是一个dll,这样Windows才能在所有进程中共享钩子代码。

与钩子相关的3个Windows API函数是:

SetWindowsHookEx、UnhookWindowsHookEx、CallNextHookEx,它们的简要说明如下:

HHOOK SetWindowsHookEx( 
int  idHook, 
HOOKPROC lpfn, 
HINSTANCE hMod, 
DWORD dwThreadId); 

idHook -- 系统钩子类型,实际上是一个int值,具体的定义请看MSDN

lpfn -- 钩子回调函数指针,当收到钩子消息时就执行这个回调函数,回调函数有3个参数,不同类型的钩子这3个参数有不同的含义,具体请看MSDN。

hMod -- DLL实例句柄(我猜是这样,我不熟悉Win32API编程),当钩子为系统钩子时这个参数是必须的,如果是单个程序或者线程使用的钩子那么可以不用这个值。

dwThreadId -- 线程ID,如果是单个程序或者线程使用的钩子这个参数是必须的。

SetWindowsHookEx返回所设置的钩子的句柄。

BOOL UnhookWindowsHookEx(HHOOK hhk);

hhk -- 所要注销的钩子的句柄

UnhookWindowsHookEx返回注销钩子是否成功。

LRESULT CallNextHookEx( 
HHOOK hhk, 
int  nCode, 
WPARAM wParam, 
LPARAM lParam); 

hhk -- 起始钩子句柄,如果是在钩子回调函数中调用CallNextHookEx时传的通常是本钩子句柄。

nCode -- 钩子回调函数参数1,具体含义视钩子类型而定。

wParam -- 钩子回调函数参数2,具体含义视钩子类型而定。

lParam -- 钩子回调函数参数3,具体含义视钩子类型而定。

从以上3个函数的简要说明可以看出所用到的参数几乎都是简单的参数,稍微复杂就是回调函数(在C#中用delegate类型来实现,后面会提到),但是最让人头疼的就是DLL的实例句柄,C#制作的DLL并不像C做的DLL有DllMain入口可以接受到DLL实例句柄。

我目前唯一的办法就是使用C做一个系统钩子DLL再让C#调用。底下是DLL的代码。

#define  _WIN32_WINNT 0x0500 

#include  < Windows.h >  
#include  < WinUser.h >  

#define  Dll_Export __declspec(dllexport) 

/* DLL实例句柄 */  

HINSTANCE instance  =  NULL; 

BOOL APIENTRY DllMain(HINSTANCE hInstance, DWORD  ul_reason_for_call, LPVOID lpReserved) 

 instance  =  hInstance; 
     return  TRUE; 
}  

/*  
*功能:设置系统钩子 
*hookType -- 钩子类型 
*hookproc -- 钩子回调函数 
*/  

Dll_Export HHOOK SetHook( int  hookType,HOOKPROC hookproc) 

  return  SetWindowsHookEx(hookType, hookproc, instance, NULL); 
}  

/*  
*功能:注销钩子 
*hook -- 钩子句柄 
*/  
Dll_Export BOOL UnHook(HHOOK hook) 

  if (hook  !=  NULL) 
   return  UnhookWindowsHookEx(hook); 
  else  
   return   0 ; 
}  

然后在C#项目中创建一个系统钩子类,提供创建钩子和注销钩子的接口,代码如下

public   class  Hook 

     [DllImport( " LowLevelHook.dll " )] 
      public   extern   static  IntPtr SetHook( int  hookType, HookProc hookProc); 

     [DllImport( " LowLevelHook.dll " )] 
      public   extern  staticbool UnHook(IntPtr hook); 
 }

 上面用到的User32.HookProc类型不是.NET框架提供的,是自己定义的一个委托类型,声明如下

public   delegate   int  HookProc( int  nCode, IntPtr wParam, IntPtr lParam); 

现在你的C#程序就可以使用各种系统钩子了,我们目前已经使用的有低级别鼠标钩子和低级别键盘钩子。

应用低级别鼠标钩子时会遇到这样一个问题:

低级别鼠标钩子的回调函数lParam是一个MSLLHOOKSTRUCT结构体指针,C#中怎么获取这个结构体的实例呢?实现代码如下

MSLLHOOKSTRUCT _mstr; 
unsafe

   _mstr  =* (User32.MSLLHOOKSTRUCT * )lParam.ToPointer(); 
 }

通过声明非安全代码来获取指针所指对象。

MSLLHOOKSTRUCT结构体的C#定义如下:

[StructLayout(LayoutKind.Sequential)] 
public   struct  MSLLHOOKSTRUCT 

      public  Point Point; 
      public   int  MouseData; 
      public   int  Flags; 
      public   int  Time; 
      public   int  ExtraInfo; 
 }