C#系統鉤子

iDotNetSpace發表於2009-07-17

這幾天用C#做了一個抓圖軟體,其中用到了系統鉤子技術。

在這裡發表下自己用C#實現系統鉤子的心得,希望對我的朋友們有所幫助。

看了很多資料,都提到系統鉤子(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)  
 
C#系統鉤子 
/* DLL例項控制程式碼 */  

HINSTANCE instance 
 =  NULL; 

BOOL APIENTRY DllMain(HINSTANCE hInstance, DWORD  ul_reason_for_call, LPVOID lpReserved) 
C#系統鉤子
 
 instance 
 =  hInstance; 
    
 return  TRUE; 
}
 
 

C#系統鉤子
 /*  
*功能:設定系統鉤子 
*hookType -- 鉤子型別 
*hookproc -- 鉤子回撥函式 
 */ 
 

Dll_Export HHOOK SetHook(
 int  hookType,HOOKPROC hookproc) 
C#系統鉤子
 
 
 return  SetWindowsHookEx(hookType, hookproc, instance, NULL); 
}
 
 

C#系統鉤子
 /*  
*功能:登出鉤子 
*hook -- 鉤子控制程式碼 
 */ 
 
Dll_Export BOOL UnHook(HHOOK hook) 
C#系統鉤子
 
 
 if (hook  !=  NULL) 
  
 return  UnhookWindowsHookEx(hook); 
 
 else  
  
 return   0 
}
 
 

然後在C#專案中建立一個系統鉤子類,提供建立鉤子和登出鉤子的介面,程式碼如下 

 public   class  Hook 
C#系統鉤子
 
     [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 
C#系統鉤子 

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

通過宣告非安全程式碼來獲取指標所指物件。

MSLLHOOKSTRUCT結構體的C#定義如下:

 [StructLayout(LayoutKind.Sequential)] 
 public   struct  MSLLHOOKSTRUCT 
C#系統鉤子
 
     
 public  Point Point; 
     
 public   int  MouseData; 
     
 public   int  Flags; 
     
 public   int  Time; 
     
 public   int  ExtraInfo; 
 }

      PS: 附件--系統鉤子的原始碼與DLL

補充HookType列舉值,很抱歉一時疏忽忘記寫出來,這些值可以在Win32 API 的相關標頭檔案中找到,有LL字樣的就是低階鉤子:

 
         
public   enum  HookTypes:  int 
C#系統鉤子          
{
            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 
        
        }


雖然上篇文章已經有但是還是要重點重複說明下CallNextHookEx函式,這個函式的功能是在執行完系統鉤子的回撥函式後接著呼叫下一個鉤子函式,當設定的鉤子是底層鍵盤或者滑鼠鉤子時如果不這麼做將會時鍵盤和滑鼠"失靈"。

        [DllImport("user32.dll")]
        
public static extern int CallNextHookEx(IntPtr hookHandle, int nCode, IntPtr wParam, IntPtr lParam);

這個函式第一個引數是鉤子的控制程式碼,在建立鉤子時返回來的那個就是,後面3個引數和鉤子回撥函式的3個引數一一對應,照傳就可以。

因為公司現在裝得是VS2005所以我只能先用VS2005做個試驗程式了,這個程式功能是鎖定滑鼠一定時間,需要有.NET Framework 2.0 Runtime才能執行,我會盡快找臺裝VS2003的電腦做個.NET 1.1的範例的。

可執行檔案:http://files.cnblogs.com/BG5SBK/HookTest_NET2_Bin.rar
專案檔案:http://files.cnblogs.com/BG5SBK/HookTest_NET2_Source.rar
系統鉤子檔案:http://files.cnblogs.com/BG5SBK/LowLevelHook.rar

 

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/12639172/viewspace-609492/,如需轉載,請註明出處,否則將追究法律責任。

相關文章