C#系統鉤子
這幾天用C#做了一個抓圖軟體,其中用到了系統鉤子技術。
在這裡發表下自己用C#實現系統鉤子的心得,希望對我的朋友們有所幫助。
看了很多資料,都提到系統鉤子(Hook)必須是一個dll,這樣Windows才能在所有程式中共享鉤子程式碼。
與鉤子相關的3個Windows API函式是:
SetWindowsHookEx、UnhookWindowsHookEx、CallNextHookEx,它們的簡要說明如下:
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返回登出鉤子是否成功。
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的程式碼。
#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#專案中建立一個系統鉤子類,提供建立鉤子和登出鉤子的介面,程式碼如下
{
[DllImport( " LowLevelHook.dll " )]
public extern static IntPtr SetHook( int hookType, HookProc hookProc);
[DllImport( " LowLevelHook.dll " )]
public extern staticbool UnHook(IntPtr hook);
}
上面用到的User32.HookProc型別不是.NET框架提供的,是自己定義的一個委託型別,宣告如下
現在你的C#程式就可以使用各種系統鉤子了,我們目前已經使用的有低階別滑鼠鉤子和低階別鍵盤鉤子。
應用低階別滑鼠鉤子時會遇到這樣一個問題:
低階別滑鼠鉤子的回撥函式lParam是一個MSLLHOOKSTRUCT結構體指標,C#中怎麼獲取這個結構體的例項呢?實現程式碼如下
unsafe
{
_mstr =* (User32.MSLLHOOKSTRUCT * )lParam.ToPointer();
}
通過宣告非安全程式碼來獲取指標所指物件。
MSLLHOOKSTRUCT結構體的C#定義如下:
public struct MSLLHOOKSTRUCT
{
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
{
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函式,這個函式的功能是在執行完系統鉤子的回撥函式後接著呼叫下一個鉤子函式,當設定的鉤子是底層鍵盤或者滑鼠鉤子時如果不這麼做將會時鍵盤和滑鼠"失靈"。
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/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- 系統鉤子的使用 (轉)
- 遮蔽系統熱鍵鉤子Hook程式Hook
- C#實現滑鼠、鍵盤鉤子C#
- 純C#鉤子實現及應用(轉)C#
- PHP系列之鉤子PHP
- React Hooks 鉤子特性ReactHook
- 鉤子(hook)是啥Hook
- vue-router的鉤子Vue
- Vue 生命週期鉤子Vue
- PHP之鉤子行為PHP
- WINDOWS鉤子函式(轉)Windows函式
- VC:滑鼠鉤子函式函式
- JVM鉤子函式的使用JVM函式
- svn:鉤子post-commitMIT
- Vue的鉤子函式[路由導航守衛、keep-alive、生命週期鉤子]Vue函式路由Keep-Alive
- 新增表單請求後鉤子
- Vue生命週期鉤子函式Vue函式
- Vue生命週期鉤子簡介Vue
- gpio子系統與pinctrl子系統通用APIAPI
- 外掛移植後,鉤子不起作用。
- Vue 生命週期與鉤子函式Vue函式
- 鉤子函式的執行機理函式
- wordpress的save_post鉤子注意點
- Vue例項的生命週期鉤子Vue
- before-after-hook鉤子函式Hook函式
- 從JDK原始碼看關閉鉤子JDK原始碼
- vue生命週期鉤子,一張圖片Vue
- EVC程式設計點滴四 - 鉤子C程式程式設計
- 訊息鉤子函式入門篇函式
- SDD子系統
- 談談 React 新的生命週期鉤子React
- Sequelize 中文文件 v4 – Hooks – 鉤子Hook
- wordpress 當更新主題時候的鉤子
- Vue路由鉤子 afterEach beforeEach區別Vue路由
- 有關windows鉤子使用的兩篇文章Windows
- Win32全域性鉤子實現 (轉)Win32
- 訊息鉤子函式入門篇 (轉)函式
- Linux驅動之GPIO子系統和pinctrl子系統Linux