行者的学习博客

  博客园 :: 首页 :: 博问 :: 闪存 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理 ::

最近学着编写钩子,花了好几天终于有点头绪,总结一下写在下面:

1、使用C#编写局部钩子

  C#编写全局钩子时,我用的时使用C#编写一个dll文件,再使用C#窗体调用该dll文件(不是说全局钩子只能使用DLL么),结果很多消息检测不到,甚至有些钩子就不能成功,所以目前只能用它做局部钩子:

声明API函数:

[DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall, SetLastError = true)]
        private static extern int SetWindowsHookEx(int idHook,HookProc lpfn,IntPtr hMod,int dwThreadId);

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

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

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

//定义回调函数委托

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

//声明变量
         private const int WH_CBT = 5;
        private const int HCBT_MOVESIZE = 0;
        private const int HCBT_MINMAX =1;

//设置钩子       

public void sethook()
        {
CBTProc = new HookProc(CBTProchook);

hmenuhook = SetWindowsHookEx(WH_CBT,CBTProcIntPtr.Zero, GetCurrentThreadId());
         }

注意:IntPtr hMod为dll的实例句柄,当是局部钩子时为NULL,int dwThreadId为当前线程ID,如果是全局钩子就设为0;对于C#获取DLL的实例句柄:(IntPtr)Marshal.GetHINSTANCE(Assembly.GetExecutingAssembly().GetModules()[0]),要增加using System.Reflection;命名空间

//编写回调函数

        private int CBTProchook(int nCode, int wParam, IntPtr lParam)
        {
            MessageBox.Show("开始");
            if (nCode == HC_ACTION)
            {
                MessageBox.Show("asf");
            }
            return CallNextHookEx(hmenuhook, nCode, wParam, lParam);
        }

//取消钩子

UnhookWindowsHookEx(hmenuhook);

2、使用C++和C#制作全局钩子

使用C++制作DLL,再用C#调用DLL中的方法,我使用的是VS2005,新建win32 dll空文件,添加hook.cpp和hook.def文件,在hook.cpp文件中添加代码:

#include <Windows.h>

HOOK g_CBTmsg;

//声明共享变量

#pragma data_seg("mydata")
HWND lms_hwnd=NULL;
HWND menu_hwnd=NULL;
#pragma data_seg()
#pragma comment(linker,"/section:mydata,RWS")

//设置钩子 其中接收两个句柄参数

 void sethook(HWND lmshwnd,HWND menuhwnd)
{
 lms_hwnd=lmshwnd;
 menu_hwnd=menuhwnd;
 g_CBTmsg=SetWindowsHookEx(WH_CBT,CBTProc,GetModuleHandle(L"hook"),0);

} //GetModuleHandle(L"hook")  获得当前的即dll实例句柄

//设置回调函数

LRESULT CALLBACK CBTProc(int nCode, WPARAM wParam,LPARAM lParam)
{

  ... ...具体参见MSDN

}

填写hook.def

LIBRARY "hook"   //dll名称
EXPORTS
sethook  @2      //输出函数

VS2005与VS6.0有点不同,不会自己读取def文件,在工程属性>linker>input>modile definition file中输入hook.def,编译即可生成dll文件和lib文件。注意在debug和Release中都要添加。

使用C#调用c++做的dll,我是显式调用的:

[DllImport("hook.dll", EntryPoint = "sethook", ExactSpelling = false, CallingConvention = CallingConvention.Cdecl)]
public static extern int sethook(IntPtr lmshwnd, IntPtr menuhwnd);

再调用函数即可。

c#根据进程名获取主窗体的句柄

Process[] LmsProcess = Process.GetProcessesByName("notepad");

LmsProcess[0].MainWindowHandle;

该方法非常使用,但不知道在MFC或API函数中怎么实现,还请各位高手指点。急......................

sethook(lms_hwnd, this.Handle);    给dll中的方法传递两句柄参数

posted on 2009-03-11 16:59  ylclass  阅读(1100)  评论(0编辑  收藏  举报