[C#] Easy Hook Library

简介

.NET似乎都没有比较好用的Hook类库,那就只好自己来做一个。


设计概念

原先我只是想将Hook的API做一些简单的封装,将其封装成一个Hook类,做一做发现其实Hook其实也不多,那乾脆先用enum将所有的hook type(参考:http://msdn.microsoft.com/en-us/library/ms644959%28v=vs.85%29.aspx)一并声明好了

因此我利用Dictionary数据结构,Key为自定的HookType,Value为自行封装的Hook类,并用一个HookManager来管理Dictionary,对Hook做Register跟Unregister的动作。

同时在register时提供自定义的delegate,以实践自定义的hookproc。


public enum HookType
{
    WH_MSGFILTER = -1,
    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_DEBUG = 9,
    WH_SHELL = 10,
    WH_FOREGROUNDIDLE = 11,
    WH_CALLWNDPROCRET = 12,
    WH_KEYBOARD_LL = 13,
    WH_MOUSE_LL = 14
}

关于HookType中的WH_XXXX数值,请参照WinUser.h中的声明。


class _HookProc
{
    #region "Declare API for Hook"
    [DllImport("user32.dll", CharSet = CharSet.Auto,
    CallingConvention = CallingConvention.StdCall)]
    static extern int SetWindowsHookEx(int idHook, _HookProcHandler lpfn,
    IntPtr hInstance, int threadId);

    [DllImport("user32.dll", CharSet = CharSet.Auto,
    CallingConvention = CallingConvention.StdCall)]
    static extern bool UnhookWindowsHookEx(int idHook);

    [DllImport("user32.dll", CharSet = CharSet.Auto,
    CallingConvention = CallingConvention.StdCall)]
    static extern int CallNextHookEx(int idHook, int nCode,
    IntPtr wParam, IntPtr lParam);

    [DllImport("kernel32.dll")]
    static extern int GetCurrentThreadId();
    #endregion

    #region "Hook Proc"
    int MyHookProc(int nCode, IntPtr wParam, IntPtr lParam)
    {
        if (m_CustomHookProc != null)
            m_CustomHookProc(nCode, wParam, lParam);
        return CallNextHookEx(m_HookHandle, nCode, wParam, lParam);
    }
    #endregion

    CustomHookProc.HookProcHandler m_CustomHookProc;
    delegate int _HookProcHandler(int nCode, IntPtr wParam, IntPtr lParam);
    _HookProcHandler m_KbdHookProc;
    int m_HookHandle = 0;

    public _HookProc(HookType a_eHookType, CustomHookProc.HookProcHandler a_pHookProc)
    {
        m_CustomHookProc = a_pHookProc;
        m_KbdHookProc = new _HookProcHandler(MyHookProc);
        m_HookHandle = SetWindowsHookEx((int)a_eHookType, m_KbdHookProc, IntPtr.Zero, GetCurrentThreadId());
        if (m_HookHandle == 0)
        {
            throw new Exception(string.Format("Hook {0} to {1} Error:{2}", a_eHookType.ToString(), a_pHookProc.ToString(), Marshal.GetLastWin32Error()));
        }
    }
    ~_HookProc()
    {
        UnhookWindowsHookEx(m_HookHandle);
        Debug.WriteLine(Marshal.GetLastWin32Error());
        m_HookHandle = 0;
    }
}

public class CustomHookProc
{
    private CustomHookProc(){}
    public delegate void HookProcHandler(int nCode, IntPtr wParam, IntPtr lParam);
}


前面的几个API的声明,是在.NET中呼叫Win32 API的方法(参考:http://msdn.microsoft.com/en-us/library/aa984739%28v=VS.71%29.aspx)。

重点是在MyHookProc,SetWindowsHookEx会将Hook指到这个函数,同时在这个函数执行时,会将Hook到的讯息丢到外部的CustomHookProc.HookProcHandler Delegate。


public class HookManager
{
    private HookManager(){}

    static readonly HookManager m_instance = new HookManager();
    Dictionary<HookType, _HookProc> m_hooks = new Dictionary<HookType, _HookProc>();

    public static HookManager Instance
    {
        get { return m_instance; }
    }

    public void RegisterHook(HookType a_eHookType, CustomHookProc.HookProcHandler a_pHookProc)
    {
        if(!m_hooks.ContainsKey(a_eHookType))
        {
            m_hooks.Add(a_eHookType, new _HookProc(a_eHookType, a_pHookProc));
        }
        else
        {
            throw new Exception(string.Format("{0} already exist!", a_eHookType.ToString()));
        }
    }
    public void Unregister(HookType a_eHookType)
    {
        m_hooks.Remove(a_eHookType);
    }
}

HookManager类是一个单例类,它负责维护所有的Hook。


private void Form1_Load(object sender, EventArgs e)
{
    HookManager.Instance.RegisterHook(HookType.WH_KEYBOARD, new CustomHookProc.HookProcHandler(KeyboardHookProc));
    HookManager.Instance.RegisterHook(HookType.WH_MOUSE, new CustomHookProc.HookProcHandler(MouseHookProc));
}
void KeyboardHookProc(int nCode, IntPtr wParam, IntPtr lParam)
{
    KeyStateInfo ctrlKey = KeyboardInfo.GetKeyState(Keys.ControlKey);
    KeyStateInfo altKey = KeyboardInfo.GetKeyState(Keys.Alt);
    KeyStateInfo shiftKey = KeyboardInfo.GetKeyState(Keys.ShiftKey);
    KeyStateInfo f8Key = KeyboardInfo.GetKeyState(Keys.F8);

    if (ctrlKey.IsPressed)
    {
        Console.WriteLine("Ctrl Pressed!");
    }
    if (altKey.IsPressed)
    {
        Console.WriteLine("Alt Pressed!");
    }
    if (shiftKey.IsPressed)
    {
        Console.WriteLine("Shift Pressed!");
    }
    if (f8Key.IsPressed)
    {
        Console.WriteLine("F8 Pressed!");
    }
}

void MouseHookProc(int nCode, IntPtr wParam, IntPtr lParam)
{
    MouseHookStruct MyMouseHookStruct = (MouseHookStruct)Marshal.PtrToStructure(lParam, typeof(MouseHookStruct));

    if (nCode >= 0)
    {
        String strCaption = "x = " +
        MyMouseHookStruct.pt.x.ToString("d") +
        "  y = " +
        MyMouseHookStruct.pt.y.ToString("d");
        Form tempForm = Form.ActiveForm;

        tempForm.Text = strCaption;
    }
}

封装完毕后,使用起来就非常简单

HookManager.Instance.RegisterHook(HookType.WH_KEYBOARD, new CustomHookProc.HookProcHandler(KeyboardHookProc));
HookManager.Instance.RegisterHook(HookType.WH_MOUSE, new CustomHookProc.HookProcHandler(MouseHookProc));

像这样使用,而且在HookProc中也不需要去管return CallNextHookEx(m_HookHandle, nCode, wParam, lParam);

只需针对自己所要处理的Hook处理即可。


参考连结

http://msdn.microsoft.com/zh-cn/magazine/cc188966(en-us).aspx


范例档下载

  • 4
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值