看看C# Hook 如何?

來源:互聯網
上載者:User

本文介紹了如何在程式中成功使用C#添加了Hook,供大家參考。

 

目前的程式中想要添加Hook,截獲鍵盤按鍵訊息,所以上網找了一下關於C# Hook的東西。發現很多人都在說在添加C#
Hook不成功和不穩定,而建議使用C++封一個Dll給C#使用。可喜的是最後我還是成功的在程式中使用C#添加了Hook,經過測試還是沒有什麼問題
的。

進行Hook需要使用三個API函數

SetWindowsHookEx 進行Hook的註冊

UnhookWindowsHookEx 取消已經註冊的Hook

CallNextHookEx 將訊息傳遞給下一個Hook函數

看一下定義

# [DllImport("user32.dll")]<br /># private static extern IntPtr SetWindowsHookEx(<br /># HookType code, HookProc func, IntPtr instance, int threadID);<br />#<br /># [DllImport("user32.dll")]<br /># private static extern int UnhookWindowsHookEx(IntPtr hook);<br />#<br /># [DllImport("user32.dll")]<br /># private static extern int CallNextHookEx(<br /># IntPtr hook, int code, IntPtr wParam, ref KBDLLHOOKSTRUCT lParam);

定義兩個event提供給外界使用

 

# public delegate void HookEventHandler(object sender, HookEventArgs e);<br /># public event HookEventHandler KeyDown;<br /># public event HookEventHandler KeyUp;

 

因為要接收的是鍵盤的訊息所以要定義一些訊息,和我們要接收的結構。

 

1. public class HookEventArgs : EventArgs<br /> 2. {<br /> 3. // using Windows.Forms.Keys instead of Input.Key since the Forms.Keys maps<br /> 4. // to the Win32 KBDLLHOOKSTRUCT virtual key member, where Input.Key does not<br /> 5. public Keys Key;<br /> 6. public bool Alt;<br /> 7. public bool Control;<br /> 8. public bool Shift;<br /> 9.<br /> 10. public HookEventArgs(UInt32 keyCode)<br /> 11. {<br /> 12. // detect what modifier keys are pressed, using<br /> 13. // Windows.Forms.Control.ModifierKeys instead of Keyboard.Modifiers<br /> 14. // since Keyboard.Modifiers does not correctly get the state of the<br /> 15. // modifier keys when the application does not have focus<br /> 16. this.Key = (Keys)keyCode;<br /> 17. this.Alt = (System.Windows.Forms.Control.ModifierKeys & Keys.Alt) != 0;<br /> 18. this.Control = (System.Windows.Forms.Control.ModifierKeys & Keys.Control) != 0;<br /> 19. this.Shift = (System.Windows.Forms.Control.ModifierKeys & Keys.Shift) != 0;<br /> 20. }<br /> 21. }<br /> 22.<br /> 23. private enum HookType : int<br /> 24. {<br /> 25. WH_JOURNALRECORD = 0,<br /> 26. WH_JOURNALPLAYBACK = 1,<br /> 27. WH_KEYBOARD = 2,<br /> 28. WH_GETMESSAGE = 3,<br /> 29. WH_CALLWNDPROC = 4,<br /> 30. WH_CBT = 5,<br /> 31. WH_SYSMSGFILTER = 6,<br /> 32. WH_MOUSE = 7,<br /> 33. WH_HARDWARE = 8,<br /> 34. WH_DEBUG = 9,<br /> 35. WH_SHELL = 10,<br /> 36. WH_FOREGROUNDIDLE = 11,<br /> 37. WH_CALLWNDPROCRET = 12,<br /> 38. WH_KEYBOARD_LL = 13,<br /> 39. WH_MOUSE_LL = 14<br /> 40. }<br /> 41.<br /> 42. public struct KBDLLHOOKSTRUCT<br /> 43. {<br /> 44. public UInt32 vkCode;<br /> 45. public UInt32 scanCode;<br /> 46. public UInt32 flags;<br /> 47. public UInt32 time;<br /> 48. public IntPtr extraInfo;<br /> 49. }

 

關鍵的在這裡註冊C# Hook

 

1. private void Install()<br /> 2. {<br /> 3. if (_hookHandle != IntPtr.Zero)<br /> 4. return;<br /> 5.<br /> 6. Module[] list = System.Reflection.Assembly.GetExecutingAssembly().GetModules();<br /> 7. System.Diagnostics.Debug.Assert(list != null && list.Length > 0);<br /> 8.<br /> 9. _hookHandle = SetWindowsHookEx(_hookType,<br /> 10. _hookFunction, Marshal.GetHINSTANCE(list[0]), 0);<br /> 11.<br /> 12. }

 

哦,還有HookType _hookType = HookType.WH_KEYBOARD_LL; 因為要截獲鍵盤訊息

還有_hookFunction = new HookProc(HookCallback);

其實最關鍵的是Marshal.GetHINSTANCE(list[0])得到當前程式的instance,這樣這個C# Hook就是全域的C# Hook,這個位置也可以是null,這樣就不是全域C# Hook。

有個很奇怪的現象就是這個函數,在調試狀態執行不能成功,而做成Release以後運行成功,所以你在做程式時,不要因為調試失敗而對這個函數有懷疑,編一個Release版本的程式,獨立運行再試一下。我使用的環境是VS2005 + Vista。

接收訊息的函數

 

1. private int HookCallback(int code, IntPtr wParam, ref KBDLLHOOKSTRUCT lParam)<br /> 2. {<br /> 3. if (code < 0)<br /> 4. return CallNextHookEx(_hookHandle, code, wParam, ref lParam);<br /> 5.<br /> 6. if ((lParam.flags & 0x80) != 0 && this.KeyUp != null)<br /> 7. this.KeyUp(this, new HookEventArgs(lParam.vkCode));<br /> 8.<br /> 9. if ((lParam.flags & 0x80) == 0 && this.KeyDown != null)<br /> 10. {<br /> 11. this.KeyDown(this, new HookEventArgs(lParam.vkCode));<br /> 12. if (lParam.vkCode == 44)<br /> 13. {<br /> 14. return 1;<br /> 15. }<br /> 16. }<br /> 17.<br /> 18. return CallNextHookEx(_hookHandle, code, wParam, ref lParam);<br /> 19. }

 

這裡會區分KeyUp和KeyDown,注意一定要調用CallNextHookEx,這樣會將這個訊息在系統中繼續傳遞,這很重要。除非你想阻止這個訊息,也不希望其他程式再處理這個訊息。

下面最後的操作,釋放註冊。

 

1. private void Uninstall()<br /> 2. {<br /> 3. if (_hookHandle != IntPtr.Zero)<br /> 4. {<br /> 5. UnhookWindowsHookEx(_hookHandle);<br /> 6. _hookHandle = IntPtr.Zero;<br /> 7. }<br /> 8. }

 

 

 

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.