您的位置:新葡亰496net > 奥门新萄京娱乐场 > 新葡亰496net:三个鼠标钩子实例,动态更新窗体

新葡亰496net:三个鼠标钩子实例,动态更新窗体

发布时间:2019-12-10 13:46编辑:奥门新萄京娱乐场浏览(193)

    新葡亰496net:三个鼠标钩子实例,动态更新窗体。前言

      在说C# Hook以前,大家先来讲说怎么是Hook手艺。相信大家都接触过外挂,不管是订正游戏顾客端的同意,盗取密码的也罢,它们都以何许达成的啊?

      实际上,Windows平台是基于事件驱动机制的,整个系统都以因此消息的传递来贯彻的。当进度有响适那个时候候(满含响应鼠标和键盘事件卡塔尔国,则Windows会向应用程序发送五个消息给应用程序的信息队列,应用程序进而从新闻队列中收取消息并发送给相应窗口进行管理。

      而Hook则是Windows音信管理体制的二个平台,应用程序能够在上面安装子程以监视钦命窗口的某种消息,并且所监视的窗口能够是别的进度所创办的。当音信达到后,在对象窗口管理函数在此以前管理它。钩子机制允许应用程序截获管理window音讯或特定事件。

      所以Hook就能够实以后键盘/鼠标响应后,窗口处理音讯早前,就对此音讯举行拍卖,譬如监听键盘输入,鼠标点击坐标等等。有些盗号木马正是Hook了钦点的进度,进而监听键盘输入了怎么内容,进而偷取账户密码。

         趁空闲的岁月,对键盘钩子进行了读书,通过C#那门语言来设计和促成:上面是笔者设计的类图:

    HOOK API (风流罗曼蒂克)——HOOK功底 贰个鼠标钩子实例,apihook

    HOOK API (后生可畏)——HOOK幼功 三个鼠标钩子实例

     

    意气风发、基本概念:

    今日收取顾客新的机能必要,要在原本的叁天性质查询窗体中增加叁个新的功效开关。那一个成效附近轻巧,实际上从版本更新和后期维护的角度来思忖,直接改造原本的窗体并非一个很好的实施方案。后来跟贰个同事切磋,他提出用Win32中的钩子机制来贯彻窗体的改过,并把新职能的程序逻辑单独包装,那样做会下降新扩大功效与原来程序的耦合度,达成了平价的送别,易于早先时期维护,适应性强。

    C# Hook

      大家知道C#是运作在.NET平台之上,并且是基于CL奥迪Q5动态运维的,所以一定要操作封装好的函数,且不或然直接操作内部存储器数据。並且在C#常用的功力中,并未有封装Hook相关的类与方法,所以若是用C#贯彻Hook,必得运用调用WindowsAPI的点子进行落到实处。

      WindowsAPI函数归于非托管类型的函数,大家在调用时必得依照以下几步:

      1、查找满含调用函数的DLL,如User32.dll,Kernel32.dll等。

      2、将该DLL加载到内部存款和储蓄器中,并注脚入口

      3、将所需参数转变为C#存在的类别,如指针对应Intptr,句柄对应int类型等等

      4、调用函数

      我们本篇须要运用的函数有以下多少个:

      SetWindowsHookEx     用于安装钩子

      UnhookWindowsHookEx   用于卸载钩子

      CallNextHookEx      推行下三个钩子

      详细API介绍请参谋MSDN官方证明

      接下去在C#中要求首先证明此API函数:

    [DllImport("user32.dll",CharSet=CharSet.Auto,CallingConvention=CallingConvention.StdCall)]
    public static extern int SetWindowsHookEx(int idHook, HookProc lpfn,IntPtr hInstance, int threadId);
    
    [DllImport("user32.dll",CharSet=CharSet.Auto,CallingConvention=CallingConvention.StdCall)]
    public static extern bool UnhookWindowsHookEx(int idHook);
    
    [DllImport("user32.dll",CharSet=CharSet.Auto,CallingConvention=CallingConvention.StdCall)]
    public static extern int CallNextHookEx(int idHook, int nCode,IntPtr wParam, IntPtr lParam);
    

      注解后就能够兑现调用,SetWindowsHookEx(卡塔尔(قطر‎把叁个应用程序定义的钩子程安装到钩子链表中,SetWindowsHookEx函数总是在Hook链的始发安装Hook子程。当钦命项目标Hook监视的风浪爆发时,系统就调用与这么些Hook关联的Hook链的发端的Hook子程。每八个Hook链中的Hook子程都决定是还是不是把这么些事件传递到下二个Hook子程。Hook子程传递事件到下一个Hook子程供给调用CallNextHookEx函数。 且钩子使用完了后要求调用UnhookWindowsHookEx进行卸载,不然轻巧影响到别的钩子的履行,並且钩子太多会影响目的经过的常常运维。

      关于实例详细操作进程不再赘言,请参见: 及 

    键盘钩子满含两类:全局钩子和民用钩子,这里自个儿分成五个类来安排:

    0x00 起因

    近几年在做完成学业设计,有二个功效是内需实现对剪切板的监察和控制和经过的防终止尊崇。原来想从内核层实现,但从没头绪。最终决定从调用层出手,即接纳HOOK API的手艺来维系相应的API,进而完成预期的功力。在此样的急需下,就起来学习了HOOK API。

     

        钩子(Hook卡塔尔(قطر‎,是Windows音信管理机制的八个平台,应用程序能够在下面安装子程以监视钦定窗口的某种新闻,何况所监视的窗口能够是其余进度所创办的。当新闻抵达后,在目的窗口管理函数在此之前管理它。钩子机制允许应用程序截获处理window新闻或特定事件。
        钩子实际上是贰个管理音信的程序段,通过系统调用,把它挂入系统。每当特定的音信发出,在未曾达到目标窗口前,钩子程序就先捕获该音讯,亦即钩子函数先拿走调整权。这个时候钩子函数就可以以加工管理(改换)该音信,也足以不作管理而继续传递该新闻,还是能够强逼停止音信的传递。

    以下是有关钩子的可比详细介绍(网络资料,非原创)。

    EasyHook

      C#作者调用WindowsAPI实行Hook成效受到非常大的约束,而C 则不受此节制,由此就有风姿罗曼蒂克对聪明的人想到了智慧的艺术:使用C 将主导操作封装成库,由C#打开调用,由此诞生了宏伟的EasyHook,它不唯有使用方便,而且开源无需付费,还支持六14位版本。

      接下去我们协同使用C#操作EasyHook来兑现一个德姆o,完结对MessageBox的改写。

      首先大家创制一个WinForm项方今后相继,并累计四个类库ClassLibrary1,再从官方网址

       新葡亰496net 1

      此中WinForm程序用于获取目的经过,并对目的经过张开注入,相关手续如下:

      1、遵照进程ID获取相关过程,并判定是不是为61个人;

      2、将所需DLL注册到GAC(全局程序集缓存),注册到GAC的指标是需求在对象经过中调用EasyHook及大家所编写的DLL;

    private bool RegGACAssembly()
     {
         var dllName = "EasyHook.dll";
         var dllPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, dllName);
         if (!RuntimeEnvironment.FromGlobalAccessCache(Assembly.LoadFrom(dllPath)))
         {
             new System.EnterpriseServices.Internal.Publish().GacInstall(dllPath);
             Thread.Sleep(100);
         }
       dllName = "ClassLibrary1.dll";
         dllPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, dllName);
         new System.EnterpriseServices.Internal.Publish().GacRemove(dllPath);
         if (!RuntimeEnvironment.FromGlobalAccessCache(Assembly.LoadFrom(dllPath)))
         {
               new System.EnterpriseServices.Internal.Publish().GacInstall(dllPath);
               Thread.Sleep(100);
         }
         return true;
      } 
    

      此处须要当心,要将和煦编写的类库DLL参与GAC,需求对DLL进行强具名操作,操作方法请参见:

      3、注入目的经过,此处需使用EasyHook的RemoteHooking.Inject(卡塔尔(英语:State of Qatar)方法举办注入:

    private static bool InstallHookInternal(int processId)
    {
      try
      {
         var parameter = new HookParameter
         {
             Msg = "已经成功注入目标进程",
             HostProcessId = RemoteHooking.GetCurrentProcessId()
          };
        RemoteHooking.Inject(
                        processId,
                        InjectionOptions.Default,
                        typeof(HookParameter).Assembly.Location,
                        typeof(HookParameter).Assembly.Location,
                        string.Empty,
                        parameter
                    );
                }
                catch (Exception ex)
                {
                    Debug.Print(ex.ToString());
                    return false;
                }
                return true;
    }
    
      HookParameter类为定义在ClassLibrary1中的一个类,包含消息与进程ID:
    
     [Serializable]
        public class HookParameter
        {
            public string Msg { get; set; }
            public int HostProcessId { get; set; }
        }
    

      到这一步大家就水到渠成了对主窗体代码的编写制定,今后我们开首编写制定注入DLL的情势:

      1、先引入MessageBox相关的WindowsAPI:

    #region MessageBoxW
    
            [DllImport("user32.dll", EntryPoint = "MessageBoxW", CharSet = CharSet.Unicode)]
            public static extern IntPtr MessageBoxW(int hWnd, string text, string caption, uint type);
    
            [UnmanagedFunctionPointer(CallingConvention.StdCall, CharSet = CharSet.Unicode)]
            delegate IntPtr DMessageBoxW(int hWnd, string text, string caption, uint type);
    
            static IntPtr MessageBoxW_Hooked(int hWnd, string text, string caption, uint type)
            {
                return MessageBoxW(hWnd, "已注入-"   text, "已注入-"   caption, type);
            }
    
            #endregion
    
            #region MessageBoxA
    
            [DllImport("user32.dll", EntryPoint = "MessageBoxA", CharSet = CharSet.Ansi)]
            public static extern IntPtr MessageBoxA(int hWnd, string text, string caption, uint type);
    
            [UnmanagedFunctionPointer(CallingConvention.StdCall, CharSet = CharSet.Ansi)]
            delegate IntPtr DMessageBoxA(int hWnd, string text, string caption, uint type);
    
            static IntPtr MessageBoxA_Hooked(int hWnd, string text, string caption, uint type)
            {
                return MessageBoxA(hWnd, "已注入-"   text, "已注入-"   caption, type);
            }
    
            #endregion
    

      此中MessageBoxA与MessageBoxW是微软用来区分区别操作系统中的编码类型,早期的Windows并不归属真正的叁十几个人操作系统,实施的API函数归于ANSI类型,而从Windows二零零四从头,归于Unicode类型,Windows在实操中,调用的MessageBox会自动依据平台区分使用前者照旧后面一个,大家在这里边就须要把两岸都蕴含个中。

      而DMessageBoxA与DMessageBoxW归属IntPtr类型的寄托,用于大家在Hook函数之后传出我们供给校正的措施,此处大家转移了MessageBox的剧情和标题,分别在前缀加上了"已流入-"的符号。

      2、完毕定义之后大家就须求对函数进行Hook,此处使用LocalHook.GetProcAddress("user32.dll", "MessageBoxW"卡塔尔(قطر‎函数,通过点名的DLL与函数名,获取函数在事实上内部存储器中的地点,获取到事后,传入LocalHook.Create(卡塔尔国方法,用于创建本地钩子:

    public void Run(
                RemoteHooking.IContext context,
                string channelName
                , HookParameter parameter
                )
            {
                try
                {
                    MessageBoxWHook = LocalHook.Create(
                        LocalHook.GetProcAddress("user32.dll", "MessageBoxW"),
                        new DMessageBoxW(MessageBoxW_Hooked),
                        this);
                    MessageBoxWHook.ThreadACL.SetExclusiveACL(new int[1]);
    
                    MessageBoxAHook = LocalHook.Create(
                        LocalHook.GetProcAddress("user32.dll", "MessageBoxA"),
                        new DMessageBoxW(MessageBoxA_Hooked),
                        this);
                    MessageBoxAHook.ThreadACL.SetExclusiveACL(new int[1]);     
                }
                catch (Exception ex)
                {
                    MessageBox.Show(ex.Message);
                    return;
                }
    
                try
                {
                    while (true)
                    {
                        Thread.Sleep(10);
                    }
                }
                catch
                {
    
                }
            }
    

      此中Message博克斯WHook与MessageBoxAHook均为LocalHook类型的变量,MessageBoxAHook.ThreadACL.SetExclusiveACL(new int[1]卡塔尔(قطر‎; 那句代码用于将本地钩子参加当前线程中试行。

      运营之后大家来查看Hook的效果,先展开一个测量检验窗体,弹出MessageBox,这时候MessageBox未有标题,且剧情是健康的:

        新葡亰496net 2

     

      接着大家对目的经过张开注入,获取进程ID后点击注入,提醒已经成功注入目的经过:

     

        新葡亰496net 3

     

      这时候点击指标经过Message博克斯,能够开采已经Hook成功,并转移了故事情节和标题:

     

        新葡亰496net 4

     

      至此,C#调用EasyHook对指标经过Hook已经完毕。

    新葡亰496net 5

    0x01什么是HOOK API

    HOOK(钩子,挂钩)是生机勃勃种达成Windows平台下相同于中断的体制[24]。HOOK机制允许应用程序拦截并拍卖Windows音信或钦赐事件,当钦点的新闻发出后,HOOK程序就可以在音讯达到目的窗口从前将其擒获,进而获取对音信的调节权,进而能够对该信息实行处理或订正,参加大家所需的效率。钩子按使用节制分,可分为线程钩子和连串钩子,在那之中,系统钩子具备超级大的效果与利益,大致能够兑现对具有Windows新闻的阻止、管理和监督检查。那项工夫涉及到多个关键的API,多个是SetWindowsHookEx,安装钩子;另一个是UnHookWindowsHookEx,卸载钩子。

        本文使用的HOOK API本事,是指截获系统或进度对有些API函数的调用,使得API的实践流程转向大家钦定的代码段,进而达成大家所需的意义。Windows下的种种进程均具备和睦之处空间,而且经过只可以调用其地址空间内的函数,因而HOOK API尤为关键的一步是,设法将和睦的代码段注入到对象经过中,手艺越来越贯彻对该进度调用的API进行拦截。可是微软并未提供HOOK API的调用接口,那就需求开垦者自身编制程序达成,大家所熟悉的防毒软件、防火墙软件等均运用HOOK API完成。

        日常的话,HOOK API由七个组成都部队分,即达成HOOK API的DLL文件,和开行注入的主调程序。本文选拔HOOK API 本事对剪切板相关的API 函数实行拦阻,进而达成对剪切板内容的监督检查效能,相仿选择该本事落成进度防终止成效。此中DLL文件帮忙HOOK API的兑现,而主调客商端程序将要带头化时把带有HOOK API功效的DLL随着鼠标钩子的加载注入到目的经过中,这里的鼠标钩子归属系统钩子。

     

    二、运转机制:

    基本概念:钩子(Hook卡塔尔国,是Windows新闻管理体制的贰个阳台,应用程序能够在上头安装子程以监视钦定窗口的某种信息,何况所监视的窗口能够是此外进度所创立的。当新闻到达后,在对象窗口管理函数以前管理它。钩子机制允许应用程序截获管理window信息或一定事件。

    后记

      从本次实施中大家能够心得到,C#对程序举行Hook是截然可行的,即便无法一直操作内部存款和储蓄器和地方,不过大家能够透过操作WindowsAPI与行使EasyHook的议程变成,非常是后世,大大收缩了代码数量与应用难度。

      然而EasyHook方今粤语资料相当少,小编在利用的经过中也遇上了相当的大困难,Hook别的函数的点子也不准完全完结,希望可以择善而从,与大家一块儿理念调换!

      本人刚商讨Hook时间不久,文中难免现身漏洞,恳请各位批评指正。

        源代码已经上传至百度网盘:链接: 密码: dv9b

     

     
    

     

     

    0x02 钩子的品类

    1、钩子链表和钩子子程:
        每二个Hook都有多个与之相关联的指针列表,称之为钩子链表,由系统来维护。这一个列表的指针指向钦点的,应用程序定义的,被Hook子程调用的回调函数,也正是该钩子的意气风发意气风发处理子程。当与钦命的Hook类型涉及的新闻发生时,系统就把那些音讯传递到Hook子程。一些Hook子程能够只监视信息,恐怕改过新闻,只怕结束新闻的前行,制止那一个音信传递到下五个Hook子程也许目标窗口。前段时间安装的钩放在链的伊始,而最先安装的钩子放在最终,也正是后参与的先得到调节权。

    钩子实际上是八个拍卖新闻的程序段,通过系统调用,把它挂入系统。每当特定的消息发生,在未曾达到指标窗口前,钩子程序就先捕获该新闻,亦即钩子函数先拿到调整权。那时钩子函数即能够加工管理(退换)该新闻,也能够不作管理而一连传递该音讯,还足以强迫甘休音信的传递。

       public delegate int HOOKPROC(int nCode, int wParam, int lParam);
       public enum HookType
        {
            WH_KEYBOA景逸SUVD = 2,//私有钩子
            WH_KEYBOARD_LL = 13//全局钩子
        }

    1、按事件分类

    有如下的三种常用类型

      (1) 键盘钩子和初级键盘钩子能够监视各样键盘消息。

      (2) 鼠标钩子和低端鼠标钩子可以监视种种鼠标新闻。

      (3) 外壳钩子可以监视各类Shell事件音讯。举例运营和关闭应用程序。

      (4) 日志钩子能够记下从系统新闻队列中收取的各类风云消息。

      (5) 窗口过程钩子监视全体从系统消息队列发往目的窗口的音信。

    除此以外,还大概有部分一定事件的钩提供给大家使用,非常的小器晚成一列举。

     

    上边描述常用的Hook类型:

    1、WH_CALLWNDPROC和WH_CALLWNDPROCRET Hooks

    WH_CALLWNDPROC和WH_CALLWNDPROCRET Hooks让你能够监视发送到窗口进程的新闻。系统在音讯发送到采用窗口进度以前调用WH_CALLWNDPROC Hook子程,何况在窗口进度管理完消息之后调用WH_CALLWNDPROCRET Hook子程。WH_CALLWNDPROCRET Hook传递指针到CWPRETSTRUCT构造,再传递到Hook子程。CWPRETSTRUCT结构富含了来自管理音信的窗口进程的重回值,肖似也包括了与那一个音讯关联的音信参数。

     

    2、WH_CBT Hook

    在以下事件早前,系统都会调用WH_CBT Hook子程,那一个事件包括:

    1. 激活,建立,销毁,最小化,最大化,移动,改造尺寸等窗口事件;

    2. 姣好系统指令;

    3. 来源系统消息队列中的移动鼠标,键盘事件;

    4. 新葡亰496net:三个鼠标钩子实例,动态更新窗体。设置输入大旨事件;

    5. 同盟系统音讯队列事件。

    Hook子程的重临值鲜明系统是不是允许只怕防止那几个操作中的二个。

     

    3、WH_DEBUG Hook

    在系统调用系统中与别的Hook关联的Hook子程早前,系统会调用WH_DEBUG Hook子程。你能够使用那个Hook来支配是不是同意系统调用与此外Hook关联的Hook子程。

     

    4、WH_FOREGROUNDIDLE Hook

    当应用程序的前台线程处于空闲状态时,可以动用WH_FOREGROUNDIDLE Hook实施低优先级的义务。当应用程序的前台线程大致要形成空闲状态时,系统就能够调用WH_FOREGROUNDIDLE Hook子程。

     

    5、WH_GETMESSAGE Hook

    应用程序使用WH_GETMESSAGE Hook来监视从GetMessage or PeekMessage函数再次回到的音讯。你可以选拔WH_GETMESSAGE Hook去监视鼠标和键盘输入,以致任何发送到音讯队列中的音讯。

     

    6、WH_JOURNALPLAYBACK Hook

    WH_JOUXC90NALPLAYBACK Hook使应用程序能够插入消息到系统消息队列。能够采纳那么些Hook重播通过使用WH_JOUCR-VNALRECO中华VD Hook记录下来的三番五遍的鼠标和键盘事件。只要WH_JOU奇骏NALPLAYBACK Hook已经安装,符合规律的鼠标和键盘事件就是低效的。WH_JOU路虎极光NALPLAYBACK Hook是全局Hook,它不能够象线程特定Hook相通采纳。WH_JOU本田CR-VNALPLAYBACK Hook再次来到超时值,这么些值告诉系统在拍卖来自回看Hook当前新闻早前须要等待多久(皮秒)。那就使Hook能够垄断(monopoly卡塔尔(英语:State of Qatar)实时事件的重播。WH_JOUPRADONALPLAYBACK是system-wide local hooks,它們不會被注射到其它行程位址空間。(推测开关Smart是用那一个hook做的)

     

    7、WH_JOURNALRECORD Hook

    WH_JOU福睿斯NALRECOENCORED Hook用来监视和著录输入事件。规范的,可以运用那一个Hook记录一而再的鼠标和键盘事件,然后经过行使WH_JOURNALPLAYBACK Hook来回放。WH_JOU大切诺基NALRECORubiconD Hook是全局Hook,它不能象线程特定Hook相像接受。WH_JOUOdysseyNALRECO帕杰罗D是system-wide local hooks,它們不會被注射到其余路程位址空間。

     

    8、WH_KEYBOARD Hook

    在应用程序中,WH_KEYBOA安德拉D Hook用来监视WM_KEYDOWN and WM_KEYUP新闻,这么些音讯通过GetMessage or PeekMessage function重临。能够行使那个Hook来监视输入到音信队列中的键盘消息。

     

    9、WH_KEYBOARD_LL Hook

    WH_KEYBOARD_LL Hook监视输入到线程音信队列中的键盘音讯。

     

    10、WH_MOUSE Hook

    WH_MOUSE Hook监视从GetMessage 大概 PeekMessage 函数重返的鼠标音信。使用那几个Hook监视输入到新闻队列中的鼠标音信。

     

    11、WH_MOUSE_LL Hook

    WH_MOUSE_LL Hook监视输入到线程消息队列中的鼠标音信。

     

    12、WH_MSGFILTER 和 WH_SYSMSGFILTER Hooks

    WH_MSGFILTER 和 WH_SYSMSGFILTEEnclaveHooks使咱们能够监视菜单,滚动条,音信框,对话框音信还要开掘客户使用ALT TAB or ALT ESC 组合键切换窗口。WH_MSGFILTELX570Hook只好监视传递到菜单,滚动条,新闻框的音讯,以致传递到通过设置了Hook子程的应用程序创设的对话框的音讯。WH_SYSMSGFILTE福特ExplorerHook监视全数应用程序消息。WH_MSGFILTER 和 WH_SYSMSGFILTELANDHooks使大家能够在情势循环时期过滤消息,那等价于在主新闻循环中过滤音信。通过调用CallMsgFilter function能够直接的调用WH_MSGFILTE瑞虎Hook。通过使用那些函数,应用程序可以在情势循环时期利用同后生可畏的代码去过滤音讯,仿佛在主音讯循环里同样。

     

    13、WH_SHELL Hook

    外壳应用程序能够行使WH_SHELL Hook去选择重要的通报。当外壳应用程序是激活的还要当顶层窗口建构或然消逝时,系统调用WH_SHELL Hook子程。

    WH_SHELL 共有5钟情況:

    • 即使有个top-level、unowned 窗口被发生、起成效、或是被摧毁;
    • 当Taskbar须要重画某些开关;
    • 当系统须求出示关于Taskbar的三个程序的最小化格局;
    • 当方今的键盘布局意况改换;
    • 当使用者按Ctrl Esc去施行Task Manager(或同一级其他次序)。

    鲁人持竿惯例,外壳应用程序都不吸收WH_SHELL音信。所以,在应用程序能够吸收接纳WH_SHELL新闻早先,应用程序必需调用SystemParametersInfo function注册它自个儿。

    以上是13种常用的hook类型!

     

     

        Windows 并不供给钩子子程的卸载顺序一定得和安装顺序相反。每当有一个钩子被卸载,Windows 便出狱其占用的内部存款和储蓄器,并更新任何Hook链表。假设程序安装了钩子,不过在还未有卸载钩子在此之前就甘休了,那么系统会活动为它做卸载钩子的操作。

    运维机制:

     

    2、按使用限定分类

    重要有线程钩子和系统钩子:

    (1) 线程钩子监视钦点线程的事件新闻。

    (2) 系统钩子监视系统中的所有线程的风云音讯。因为系统钩子会影响系统中装有的应用程序,所以钩子函数必需放在独立的动态链接库(DLL卡塔尔(英语:State of Qatar)

    中。那是系统钩子和线程钩子相当大的分裂之处。

        

    几点须求证明之处:

    (1) 要是对于同一事件(如鼠标音讯)既安装了线程钩子又安装了系统钩子,那么系统会自动先调用线程钩子,然后调用系统钩子。

    (2) 对同一事件信息可安装多少个钩管理进程,这几个钩子管理进程变成了钩子链。当前钩子管理终结后应把钩子新闻传递给下叁个钩子函数。何况这段日子设置的钩子放在链的启幕,而最先安装的钩放在最终,也正是后投入的先获得调控权。

    (3) 钩子非常是系统钩子会损耗音讯管理时间,收缩系统性情。唯有在供给的时候才安装钩子,在选取完结后要马上卸载。

     

        钩子子程是一个应用程序定义的回调函数(CALLBACK Function卡塔尔,不可能定义成有个别类的分子函数,只好定义为何奇之有的C函数。用以监视系统或某意气风发特定类型的事件,这个事件可以是与某大器晚成一定线程关联的,也得以是系统中装有线程的平地风波。

    1、钩子链表和钩子子程:

     

    0x03编写制定钩子程序

    编排钩子程序的手续分为三步:定义钩子函数、安装钩子和卸载钩子。

     

    1.定义钩子函数

      钩子函数是风姿浪漫种非常的回调函数。钩子监视的特定事件产生后,系统会调用钩子函数进行拍卖。不相同事件的钩函数的款型是各不相通的。上面以鼠标钩子函数例如表达钩子函数的原型:

    LRESULT CALLBACK HookProc(int nCode ,WPARAM wParam,LPARAM lParam)

    参数wParam和 lParam富含所钩音信的信息,比方鼠标地方、状态,键盘按钮等。nCode包蕴关于信息小编的新闻,比方是不是从音信队列中移出。

    大家先在钩子函数中实现自定义的成效,然后调用函数 CallNextHookEx.把钩子音信传递给钩子链的下二个钩子函数。CallNextHookEx.的原型如下:

    LRESULT CallNextHookEx( HHOOK hhk, int nCode, WPARAM wParam, LPARAM lParam )

    参数 hhk是钩子句柄。nCode、wParam和lParam 是钩子函数。

    本来也能够透过间接再次来到TRUE来放任该音讯,就拦住了该新闻的传递。

     

    2.装置钩子

      在程序起始化的时候,调用函数SetWindowsHookEx安装钩子。其函数原型为:

    HHOOK SetWindowsHookEx( int idHook,HOOKPROC lpfn, INSTANCE hMod,DWORD dwThreadId )

    参数idHook表示钩子类型,它是和钩子函数类型大器晚成黄金年代对应的。比方,WH_KEYBOA逍客D表示安装的是键盘钩子,WH_MOUSE表示是鼠标钩子等等。

      Lpfn是钩子函数之处。

      HMod是钩子函数所在的实例的句柄。对于线程钩子,该参数为NULL;对于系统钩子,该参数为钩子函数所在的DLL句柄。

       dwThreadId 钦赐钩子所监视的线程的线程号。对于全局钩子,该参数为NULL。

      SetWindowsHookEx重临所设置的钩句柄。

     

    3.卸载钩子

    当不再动用钩卯时,必得立时卸载。简单地调用函数:

    BOOL UnhookWindowsHookEx( HHOOK hhk)即可。

    值得注意的是线程钩子和种类钩子的钩子函数的职位有相当大的差距。线程钩子经常在时下线程或然当前线程派生的线程内,而系统钩子必得放在独立的动态链接库中,达成起来要麻烦一些。

        钩子子程必需比照以下的语法:

    每二个Hook都有一个与之相关联的指针列表,称之为钩子链表,由系统来维护。那一个列表的指针指向钦命的,应用程序定义的,被Hook子程调用的回调函数,也正是该钩子的种种管理子程。当与钦命的Hook类型涉及的音讯发出时,系统就把这一个音信传递到Hook子程。一些Hook子程能够只监视新闻,也许涂改消息,可能终止音信的前行,防止那一个消息传递到下一个Hook子程只怕指标窗口。近日设置的钩子放在链的早前,而最初安装的钩放在最终,也便是后投入的先获得调整权。

     

    0x04 多个实例——低等鼠标钩子程序

    由0x02节,鼠标钩子类型有多个,二个是WH_MOUSE,另八个是WH_MOUSE_LL。其中WH_MOUSE_LL Hook,WH_MOUSE_LL Hook监视输入到线程音信队列中的鼠标音讯。本例测验的是WH_MOUSE_LL。

     

    参照上一小结可以知道,编写钩子程序的八个步奏是:

    LRESULT CALLBACK HookProc(int nCode ,WPARAM wParam,LPARAM lParam)

    HHOOK SetWindowsHookEx( int idHook,HOOKPROC lpfn, INSTANCE hMod,DWORD dwThreadId )

    还索要当心一点:系统钩子必得放在独立的动态链接库中。因而,程序分成多少个部分:二个是钩子程序动态链接库,完毕了鼠标钩子程序;另二个是MFC操作窗体,对DLL实行加载和卸载,即对DLL举行测量试验。

     

    新建项目——> Visual C ——> MFC DLL

    新葡亰496net 6新葡亰496net 7新葡亰496net 8

    自定义消息

    #define WM_HOOKMSG WM_USER 106    // 自定义消息

     

    共享代码段,所有线程共享

    #pragma data_seg("SHARED")

    static HHOOK hhkMouse = NULL;            // 鼠标钩子句柄

    static HINSTANCE g_hInstance = NULL;    // 本DLL的实例句柄

    static HWND g_hWnd = NULL;                // 调用DLL的主窗口句柄

    #pragma data_seg()

    #pragma comment(linker,"/section:SHARED,rws")

     

    定义低级鼠标子函数

    LRESULT CALLBACK LowLevelMouseProc(int nCode,WPARAM wParam,LPARAM lParam)

    {

        // 有鼠标消息时,将其发给主程序

        if ( g_hWnd != NULL && nCode == HC_ACTION)

        {

            ::SendMessage(g_hWnd,WM_HOOKMSG,wParam,lParam);

        }

     

        return CallNextHookEx(hhkMouse,nCode,wParam,lParam);

     

    }

     

    安装低级鼠标子函数,从而截获系统所有的鼠标消息

    BOOL WINAPI StartHookMouse(HWND hwnd)

    {

        g_hWnd = hwnd;

        hhkMouse = SetWindowsHookEx(WH_MOUSE_LL,LowLevelMouseProc,g_hInstance,0);

        if ( NULL == hhkMouse)

        {

            return FALSE;

        }

        else

        {

            return TRUE;

        }

     

    }

     

    卸载低级鼠标钩子

    VOID WINAPI StopHookMouse()

    {

        if (hhkMouse != NULL)

        {

            ::UnhookWindowsHookEx(hhkMouse);

        }

    }

     

    获取自身的DLL句柄

    // ChookDllApp 初始化

    BOOL ChookDllApp::InitInstance()

    {

        CWinApp::InitInstance();

     

        //

        // 获取自身的dll句柄

        //

        g_hInstance = ::AfxGetInstanceHandle();

     

        return TRUE;

    }

     

    hookDll.def文件,钩子的加载和卸载函数

    ; hookDll.def : 声明 DLL 的模块参数。

     

    LIBRARY "MouseHook"

     

    EXPORTS

    ; 此处可以是显式导出

    StartHookMouse

    StopHookMouse

     

    消息定义

    #define WM_MOUSEMSG WM_USER 106

     

    添加消息映射

    BEGIN_MESSAGE_MAP(ChookWindowDlg, CDialogEx)

        

    //…… ……

     

        ON_MESSAGE(WM_MOUSEMSG,&ChookWindowDlg::OnMouseMsg) //消息映射

     

    END_MESSAGE_MAP()

     

    鼠标钩子的加载和卸载

    HINSTANCE g_hInstanceDll = NULL;

    //

    //    启动鼠标钩子

    //

    void ChookWindowDlg::OnBnClickedButtonStart()

    {

        // TODO: 在此添加控件通知处理程序代码

        g_hInstanceDll = LoadLibrary(_T("hookDll.dll"));

        if (NULL == g_hInstanceDll)

        {

            AfxMessageBox(_T("加载hookDll.dll失败"));

            return;

        }

        typedef BOOL (CALLBACK *StartHookMouse)(HWND hwnd);

        StartHookMouse startHook;

        startHook = (StartHookMouse) ::GetProcAddress(g_hInstanceDll,"StartHookMouse");

        if ( NULL == startHook )

        {

            AfxMessageBox(_T("获取 StartHookMouse 函数失败"));

            return;

        }

     

        if (startHook(this->m_hWnd))

        {

            m_List.InsertItem(m_List.GetItemCount(),_T("0"));

            m_List.SetItemText(m_List.GetItemCount()-1,1,_T("0"));

            m_List.SetItemText(m_List.GetItemCount()-1,2,_T("启动鼠标钩子成功"));

        }

        else

        {

            m_List.InsertItem(m_List.GetItemCount(),_T("0"));

            m_List.SetItemText(m_List.GetItemCount()-1,1,_T("0"));

            m_List.SetItemText(m_List.GetItemCount()-1,2,_T("启动鼠标钩子失败"));

        }

        

    }

     

    //

    // 停止鼠标钩子HOOK

    //

    void ChookWindowDlg::OnBnClickedButtonHook()

    {

        // TODO: 在此添加控件通知处理程序代码

        typedef VOID (CALLBACK *StopHookMouse)();

        StopHookMouse stopHook;

        g_hInstanceDll = LoadLibrary(_T("hookDll.dll"));

        if ( g_hInstanceDll == NULL)

        {

            AfxMessageBox(_T("加载DLL失败"));

            return;

        }

     

        stopHook = (StopHookMouse) ::GetProcAddress(g_hInstanceDll,"StopHookMouse");

        if (stopHook == NULL)

        {

            m_List.InsertItem(m_List.GetItemCount(),_T("0"));

            m_List.SetItemText(m_List.GetItemCount()-1,1,_T("0"));

            m_List.SetItemText(m_List.GetItemCount()-1,2,_T("获取函数 StopHookMouse 失败"));

            return;

        }

        else

        {

            stopHook();

            m_List.InsertItem(m_List.GetItemCount(),_T("0"));

            m_List.SetItemText(m_List.GetItemCount()-1,1,_T("0"));

            m_List.SetItemText(m_List.GetItemCount()-1,2,_T("停止HOOKMOUSE成功"));

        }

     

        if (g_hInstanceDll != NULL)

        {

            ::FreeLibrary(g_hInstanceDll);

        }

     

        // 确保list control 最后一行可见

        m_List.EnsureVisible(m_List.GetItemCount()-1,FALSE);

     

    }

     

    新葡亰496net 9

    新葡亰496net 10

     

    [cpp] view plaincopyprint?

    Windows 并不必要钩子子程的卸载顺序一定得和安装顺序相反。每当有四个钩子被卸载,Windows 便出狱其占用的内部存款和储蓄器,并更新任何Hook链表。若是程序安装了钩子,不过在未曾卸载钩子以前就终止了,那么系统会活动为它做卸载钩子的操作。

    新葡亰496net 11新葡亰496net 12Hook基类完成

    参考

    API (豆蔻年华)——HOOK基本功 三个鼠标钩子实例,apihook HOOK API (生龙活虎)HOOK幼功 多个鼠标钩子实例 0x00 起因 近期在做结业设计,有四个成效是需...

    1.  LRESULT CALLBACK HookProc  
    2.   
    3. int nCode,   
    4.    WPARAM wParam,   
    5.    LPARAM lParam  
    6.   );  

      LRESULT CALLBACK HookProc
      

      ( int nCode,

        WPARAM wParam, 
        LPARAM lParam
       );
      

    钩子子程是五个应用程序定义的回调函数(CALLBACK Function卡塔尔国,无法定义成某些类的积极分子函数,只可以定义为日常的C函数。用以监视系统或某生机勃勃特定类型的风云,那么些事件可以是与某风姿浪漫一定线程关联的,也能够是系统中有所线程的事件。

     public abstract class hook
        {
            //设置钩子
            [DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
            public static extern int SetWindowsHookEx(HookType idHook, HOOKPROC lpfn, IntPtr hInstance, int threadId);
            //抽调钩子
            [DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
            public static extern bool UnhookWindowsHookEx(int idHook);

    HookProc是应用程序定义的名字。

    钩子子程必得坚决守住以下的语法:

            [DllImport("kernel32")]
            public static extern int GetCurrentThreadId();

    nCode参数是Hook代码,Hook子程使用这些参数来规定任务。那么些参数的值注重于Hook类型,每风流倜傥种Hook都有自个儿的Hook代码特征字符集。
    wParam和lParam参数的值信任于Hook代码,然而它们的规范值是含有了有关发送或许接到音讯的新闻。

    LRESULT CALLBACK HookProc

            /// <summary>
            /// 钩子管理委托
            /// </summary>
            public HOOKPROC proc;
            /// <summary>
            /// 钩子类型
            /// </summary>
            public HookType type;
            /// <summary>
            /// 钩子的句柄
            /// </summary>
            public int hHook = 0;

    2、钩子的设置与自由:

    (

            public hook(HOOKPROC proc, HookType type)
            {
                this.proc = proc;
                this.type = type;
            }

        使用API函数SetWindowsHookEx(卡塔尔把三个应用程序定义的钩子程安装到钩子链表中。SetWindowsHookEx函数总是在Hook链的早前安装Hook子程。当内定项目标Hook监视的风云时有产生时,系统就调用与那几个Hook关联的Hook链的起来的Hook子程。每三个Hook链中的Hook子程都调整是还是不是把这一个事件传递到下二个Hook子程。Hook子程传递事件到下叁个Hook子程须要调用CallNextHookEx函数。     

          int nCode,

            public abstract int SetWindowsHookEx();
            public virtual void UnhookWindowsHookEx()
            {
                bool retKeyboard = true;
                if (hHook != 0)
                {
                    retKeyboard = UnhookWindowsHookEx(hHook);
                    hHook = 0;
                }
                if (!retKeyboard)
                {
                    throw new Exception("UnhookWindowsHookEx failed.");
                }
            }
        }

    [cpp] view plaincopyprint?

           WPARAM wParam,

     

    1. HHOOK SetWindowsHookEx(   
    2.      int idHook,      // 钩子的档案的次序,即它管理的音信类型   
    3.      HOOKPROC lpfn,   // 钩子子程的地点指针。要是dwThreadId参数为0   
    4.       // 或是三个由其他进度创建的线程的标记,   
    5.       // lpfn必须指向DLL中的钩子子程。   
    6.       // 除此以外,lpfn能够本着当前历程的生机勃勃段钩子子程代码。   
    7.       // 钩子函数的进口地址,当钩子钩到别的信息后便调用这一个函数。   
    8.      HINSTANCE hMod,  // 应用程序实例的句柄。标记包蕴lpfn所指的子程的DLL。   
    9.       // 要是dwThreadId 标志当前历程创制的贰个线程,   
    10.       // 何况子程代码坐落于当前经过,hMod必得为NULL。   
    11.       // 能够超轻松的设定其为本应用程序的实例句柄。   
    12.      DWOEnclaveD dwThreadId // 与安装的钩子子程相关联的线程的标志符。   
    13.       // 借使为0,钩子子程与有着的线程关联,即为全局钩子。   
    14.                  );   
    15.   函数成功则赶回钩子子程的句柄,失利重临NULL。  

      HHOOK SetWindowsHookEx(      int idHook, // 钩子的系列,即它管理的新闻类型      HOOKPROC lpfn, // 钩子子程的地点指针。即便dwThreadId参数为0

        // 或是一个由别的进程创建的线程的标识,
        // lpfn必须指向DLL中的钩子子程。
        // 除此以外,lpfn可以指向当前进程的一段钩子子程代码。
        // 钩子函数的入口地址,当钩子钩到任何消息后便调用这个函数。
      

           HINSTANCE hMod, // 应用程序实例的句柄。标志富含lpfn所指的子程的DLL。

        // 如果dwThreadId 标识当前进程创建的一个线程,
        // 而且子程代码位于当前进程,hMod必须为NULL。
        // 可以很简单的设定其为本应用程序的实例句柄。
      

           DWO帕杰罗D dwThreadId // 与安装的钩子程相关联的线程的标志符。

        // 如果为0,钩子子程与所有的线程关联,即为全局钩子。
      

            卡塔尔国;   函数成功则赶回钩子子程的句柄,失败再次来到NULL。

           LPARAM lParam

     

      以上所说的钩子程与线程相关联是指在生龙活虎钩子链表中发放该线程的新闻还要发送给钩子子程,且被钩子子程先管理。

    );

     

        在钩子子程中调用获得调节权的钩函数在完结对音讯的管理后,假使想要该音讯持续传递,那么它必得调用别的一个SDK中的API函数CallNextHookEx来传递它,以进行钩子链表所指的下一个钩子子程。那几个函数成功时回来钩子链中下一个钩子进程的再次来到值,再次来到值的项目信任于钩子的项目。那几个函数的原型如下:

    HookProc是应用程序定义的名字。

    新葡亰496net 13新葡亰496net 14大局钩子和民用钩子落成

    [cpp] view plaincopyprint?

    nCode参数是Hook代码,Hook子程使用这几个参数来规定职务。那个参数的值信任于Hook类型,每生机勃勃种Hook都有和好的Hook代码特征字符集。

     public class PublicHook : hook
        {
            public PublicHook(HOOKPROC proc)
                : base(proc, HookType.WH_KEYBOARD_LL)
            { }

    1. LRESULT CallNextHookEx  
    2.    (  
    3.     HHOOK hhk;  
    4.     int nCode;  
    5.     WPARAM wParam;  
    6.     LPARAM lParam;  
    7.     );  

      LRESULT CallNextHookEx (

      HHOOK hhk;
      int nCode;
      WPARAM wParam;
      LPARAM lParam;
      );
      

    wParam和lParam参数的值注重于Hook代码,可是它们的规范值是富含了有关发送只怕收受消息的音讯。

            public override int SetWindowsHookEx()
            {
                if (hHook == 0)
                    hHook = SetWindowsHookEx(this.type, this.proc, Marshal.GetHINSTANCE(Assembly.GetExecutingAssembly().GetModules()[0]), 0);
                return hHook;
            }
        }

       
    hhk为当下钩子的句柄,由SetWindowsHookEx(卡塔尔函数再次回到。
    NCode为传给钩子进程的风浪代码。
    wParam和lParam 分别是传给钩子子程的wParam值,其切实意思与钩子类型有关。
      
        钩子函数也得以因而一贯回到TRUE来屏弃该新闻,并拦截该音信的传递。否则的话,其余设置了钩子的应用程序将不会收下到钩子的通报同时还会有相当大大概产生不科学的结果。

    2、钩子的安装与释放:

        public class PrivateHook : hook
        {
            public PrivateHook(HOOKPROC proc)
                : base(proc, HookType.WH_KEYBOARD)
            { }

        钩子在接受完之后须求用UnHookWindowsHookEx(卡塔尔国卸载,不然会招致麻烦。释放钩子比较轻松,UnHookWindowsHookEx(卡塔尔国独有二个参数。函数原型如下:

    使用API函数SetWindowsHookEx(卡塔尔把四个应用程序定义的钩子程安装到钩子链表中。SetWindowsHookEx函数总是在Hook链的开端安装Hook子程。当钦定项目标Hook监视的风云发生时,系统就调用与这几个Hook关联的Hook链的早先的Hook子程。每八个Hook链中的Hook子程都调整是或不是把这么些事件传递到下一个Hook子程。Hook子程传递事件到下多个Hook子程需求调用CallNextHookEx函数。

            public override int SetWindowsHookEx()
            {
                if (hHook == 0)
                    hHook = SetWindowsHookEx(this.type, this.proc, IntPtr.Zero, GetCurrentThreadId());
                return hHook;
            }
        }

    UnHookWindowsHookEx
      (
      HHOOK hhk;
      );
    函数成功重返TRUE,不然重临FALSE。

    HHOOK SetWindowsHookEx(

     

    3、一些运营机制:

         int idHook,      // 钩子的品种,即它管理的新闻类型

     

        在Win16条件中,DLL的全局数据对各样载入它的历程来讲都以平等的;而在Win32情况中,情形却发生了变通,DLL函数中的代码所创设的别样对象(富含变量)都归调用它的线程或进程拥有。当进度在载入DLL时,操作系统自动把DLL地址映射到该进程的私人民居房空间,相当于进度的设想地址空间,并且也复制该DLL的大局数据的风度翩翩份拷贝到该进程空间。也正是说各种进度所全部的同样的DLL的大局数据,它们的称呼相通,但其值却并不一定是大器晚成律的,何况是互不干涉的。
     
     由此,在Win32遭遇下要想在四个经过中国共产党享数据,就必须要开展必要的装置。在做客同三个Dll的各进度之间分享存款和储蓄器是经过存款和储蓄器映射文件本事完结的。也可以把那个供给分享的多寡分离出来,放置在贰个独立的多寡段里,并把该段的属性设置为分享。必须给那么些变量赋初值,不然编译器会把还未赋早先值的变量放在三个叫未被初步化的数目段中。

         HOOKPROC lpfn,   // 钩子子程的地址指针。如若dwThreadId参数为0

    新葡亰496net 15新葡亰496net 16主分界面调用实现

     #pragma data_seg预管理指令用于安装分享数据段。比方:
    #pragma data_seg("SharedDataName")
    HHOOK hHook=NULL;
    #pragma data_seg()
     在#pragma data_seg("SharedDataName")和#pragma data_seg(卡塔尔之间的具有变量 将被访问该Dll的保有进程见到和分享。

                         // 或是叁个由其他进度创建的线程的标记,

    private hook hook = null;
    private void btnOpen_Click(object sender, EventArgs e)
    {
                if (this.comboBox1.SelectedIndex == 0)
                    hook = new PublicHook(MyKeyboardProc);
                else
                    hook = new PrivateHook(MyKeyboardProc);
                int hHook = hook.SetWindowsHookEx();
                if (hHook == 0)
                {
                    MessageBox.Show("设置钩子失利!");
                }
    }
    private void btnClose_Click(object sender, EventArgs e)
    {
                try
                {
                    if (hook != null)
                        hook.UnhookWindowsHookEx();
                }
                catch
                {
                    MessageBox.Show("关闭钩子战败!"卡塔尔;
                }
    }

        当进度隐式或显式调用贰个动态Curry的函数时,系统都要把那几个动态库映射到那么些进度的虚构地址空间里(以下简单称谓"地址空间"卡塔尔。那使得DLL成为进度的一片段,以这一个进程的地方实践,使用这一个进度的库房。

                         // lpfn必须指向DLL中的钩子子程。

    public int MyKeyboardProc(int nCode, int wParm, int lParam)
    {
                MessageBox.Show("你已经按下了按钮!");
                return 0;
    }

    4、系统钩子与线程钩子:

                         // 除此以外,lpfn能够本着当前历程的风华正茂段钩子子程代码。

     

        SetWindowsHookEx(卡塔尔(英语:State of Qatar)函数的结尾贰个参数决定了此钩子是系统钩子依然线程钩子。
        
        线程勾子用于监视钦赐线程的风浪消息。线程勾子日常在近些日子线程大概当前线程派生的线程内。
        
        系统勾子监视系统中的所有线程的轩然大波新闻。因为系统勾子会潜移默化系统中拥有的应用程序,所以勾子函数必得放在独立的动态链接库(DLL卡塔尔(英语:State of Qatar)中。系统活动将含有"钩子回调函数"的DLL映射到受钩子函数影响的具有进度之处空间中,将在这些DLL注入了那多少个经过。

                         // 钩子函数的进口地址,当钩子钩到其余消息后便调用这么些函数。

     

    几点表达:
     (1)如若对于同样事件(如鼠标信息)既安装了线程勾子又安装了系统勾子,那么系统会自动先调用线程勾子,然后调用系统勾子。 

         HINSTANCE hMod,  // 应用程序实例的句柄。标志富含lpfn所指的子程的

    运转后主分界面效果如下图所示:

     (2)对相像事件新闻可设置多个勾子管理进程,那个勾子管理进度形成了勾子链。当前勾子管理实现后应把勾子新闻传送给下二个勾子函数。 

    DLL。

     新葡亰496net 17

     (3)勾子极其是系统勾子会消耗新闻管理时间,减弱系统质量。独有在供给的时候才安装勾子,在动用实现后要立马卸载。

                         // 借使dwThreadId 标识当前经过成立的四个线程,

     

    三、钩子类型

                         // 並且子程代码坐落于当前进度,hMod必得为NULL。

    上边备注一下在选拔进度中部分类库表明及注意事项:

        每一体系型的Hook能够使应用程序能够监视不相同门类的种类音讯管理机制。上面描述全数能够利用的Hook类型。

                         // 能够非常轻便的设定其为本应用程序的实例句柄。

    1、AppDomain.GetCurrentThreadId(卡塔尔(قطر‎在.net 2.0中过时了,VS二〇〇七和VS二〇〇八警戒那么些措施已经不符合时机,提出利用System.Threading.Thread.CurrentThread.ManagedThreadId,但骨子里那八个值是不平等的。AppDomain.GetCurrentThreadId(卡塔尔的实际上调用Win32 API,其回到的是该线程在Windows中的ThreadId,即同那个等价:

    1、WH_CALLWNDPROC和WH_CALLWNDPROCRET Hooks

         DWO牧马人D dwThreadId // 与安装的钩子子程相关联的线程的标志符。

    [DllImport("kernel32")]
    public static extern int GetCurrentThreadId();

        WH_CALLWNDPROC和WH_CALLWNDPROCRET Hooks令你能够监视发送到窗口进程的音信。系统在新闻发送到接纳窗口进程此前调用WH_CALLWNDPROC Hook子程,况兼在窗口进度管理完新闻之后调用WH_CALLWNDPROCRET Hook子程。

                         // 如果为0,钩子子程与持有的线程关联,即为全局钩子。

    而System.Threading.Thread.CurrentThread.ManagedThreadId重返的是用作一个ManagedThread在.Net CLLX570中的ThreadId,所以那和Windows的ThreadId是全然两样的。

        WH_CALLWNDPROCRET Hook传递指针到CWPRETSTRUCT构造,再传递到Hook子程。CWPRETSTRUCT布局满含了来自管理消息的窗口进度的重返值,同样也包含了与这么些新闻关联的音讯参数。

                     );

    2、使用API函数SetWindowsHookEx(卡塔尔(قطر‎把多个应用程序定义的钩子程安装到钩子链表中。SetWindowsHookEx函数总是在Hook链的启幕安装Hook子程。当钦定项指标Hook监视的平地风波时有爆发时,系统就调用与这些Hook关联的Hook链的始发的Hook子程。每一个Hook链中的Hook子程都决定是不是把这么些事件传递到下四个Hook子程。Hook子程传递事件到下三个Hook子程必要调用CallNextHookEx函数.函数签字如下:

    2、WH_CBT Hook

      函数成功则赶回钩子子程的句柄,战败再次来到NULL。

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

        在偏下事件以前,系统都会调用WH_CBT Hook子程,那些事件包罗:
        1. 激活,创设,销毁,最小化,最大化,移动,改动尺寸等窗口事件;
        2. 完毕系统指令;
        3. 源于系统音信队列中的移动鼠标,键盘事件;
        4. 设置输入核心事件;
        5. 齐声系统消息队列事件。
        
        Hook子程的重回值鲜明系统是或不是同意恐怕防备这几个操作中的多少个。

      以上所说的钩子子程与线程相关联是指在风流倜傥钩子链表中发放该线程的新闻还要发送给钩子子程,且被钩子子程先管理。

     

    3、WH_DEBUG Hook

    在钩子子程中调用获得调节权的钩子函数在成功对音信的拍卖后,假如想要该音信持续传递,那么它必得调用其它三个SDK中的API函数CallNextHookEx来传递它,以施行钩子链表所指的下三个钩子子程。那几个函数成功时重返钩子链中下贰个钩子进度的再次来到值,再次来到值的门类看重于钩子的门类。这么些函数的原型如下:

     

        在系统调用系统中与其余Hook关联的Hook子程早先,系统会调用WH_DEBUG Hook子程。你能够接收这一个Hook来调节是不是允许系统调用与其他Hook关联的Hook子程。

    LRESULT CallNextHookEx

    新葡亰496net 18新葡亰496net 19代码

    4、WH_FOREGROUNDIDLE Hook

                      (

    HHOOK SetWindowsHookEx( 
         int idHook,      // 钩子的连串,即它管理的新闻类型
         HOOKPROC lpfn,   // 钩子子程的地址指针。假使dwThreadId参数为0
                   // 或是一个由别的进度创建的线程的标记,
                   // lpfn必需指向DLL中的钩子子程。
                   // 除此以外,lpfn能够针对当前经过的大器晚成段钩子子程代码。
                   // 钩子函数的进口地址,当钩子钩到任何新闻后便调用那几个函数。
         HINSTANCE hMod,  // 应用程序实例的句柄。标记包括lpfn所指的子程的
    DLL。
                   // 如若dwThreadId 标志当前经过创立的三个线程,
                   // 并且子程代码位于当前经过,hMod必须为NULL。
                   // 能够非常粗大略的设定其为本应用程序的实例句柄。
         DWOHavalD dwThreadId // 与安装的钩子子程相关联的线程的标记符。
                   // 借使为0,钩子子程与持有的线程关联,即为全局钩子。
                     ); 

        当应用程序的前台线程处于空闲状态时,能够利用WH_FOREGROUNDIDLE Hook实践低优先级的职分。当应用程序的前台线程大约要变为空闲状态时,系统就能调用WH_FOREGROUNDIDLE Hook子程。

                            HHOOK hhk;

    函数成功则赶回钩子子程的句柄,失利重回NULL。

    5、WH_GETMESSAGE Hook

                            int nCode;

    如上所说的钩子子程与线程相关联是指在生龙活虎钩子链表中发放该线程的新闻还要发送给钩子子程,且被钩子子程先管理。

        应用程序使用WH_GETMESSAGE Hook来监视从GetMessage or PeekMessage函数再次来到的音信。你能够行使WH_GETMESSAGE Hook去监视鼠标和键盘输入,以至其余发送到音讯队列中的新闻。

                            WPARAM wParam;

     3、系统钩子和线程钩子:

    6、WH_JOURNALPLAYBACK Hook

                            LPARAM lParam;

    SetWindowsHookEx(卡塔尔(قطر‎函数的终极二个参数决定了此钩子是系统钩子还是线程钩子。

        WH_JOU兰德酷路泽NALPLAYBACK Hook使应用程序能够插入消息到系统消息队列。能够接纳那几个Hook重播通过运用WH_JOUEvoqueNALRECOXC60D Hook记录下来的接连的鼠标和键盘事件。只要WH_JOUGL450NALPLAYBACK Hook已经安装,符合规律的鼠标和键盘事件正是不著见到成效的。WH_JOU卡宴NALPLAYBACK Hook是全局Hook,它不可能象线程特定Hook相符接受。WH_JOU凯雷德NALPLAYBACK Hook再次回到超时值,那么些值告诉系统在管理来自重放Hook当前信息从前供给翘首以待多久(飞秒)。那就使Hook能够操纵实时事件的回看。WH_JOU翼虎NALPLAYBACK是system-wide local hooks,它們不會被注射到其它路程位址空間。

                       );

    线程勾子用于监视钦命线程的平地风波音信。线程勾子日常在这里时此刻线程只怕当前线程派生的线程内。

    7、WH_JOURNALRECORD Hook

    hhk为当前钩子的句柄,由SetWindowsHookEx(卡塔尔(قطر‎函数重返。

    系统勾子监视系统中的所有线程的事件音信。因为系统勾子会默化潜移系统中持有的应用程序,所以勾子函数必得放在独立的动态链接库(DLL卡塔尔(英语:State of Qatar)中。系统活动将包蕴"钩子回调函数"的DLL映射到受钩子函数影响的享有进度的地址空间中,即将那么些DLL注入了那多少个经过。

        WH_JOUCR-VNALRECOHighlanderD Hook用来监视和著录输入事件。标准的,能够选拔这些Hook记录一而再的鼠标和键盘事件,然后经过行使WH_JOURNALPLAYBACK Hook来回放。WH_JOU纳瓦拉NALRECOHavalD Hook是全局Hook,它不可能象线程特定Hook同样采纳。WH_JOU传祺NALRECOKugaD是system-wide local hooks,它們不會被注射到其余路程位址空間。

    NCode为传给钩子进度的事件代码。

    几点表达:

    8、WH_KEYBOARD Hook

    wParam和lParam 分别是传给钩子子程的wParam值,其现实意思与钩子类型有关。

    (1)要是对于同样事件(如鼠标音讯)既安装了线程勾子又安装了系统勾子,那么系统会自行先调用线程勾子,然后调用系统勾子。

        在应用程序中,WH_KEYBOAHighlanderD Hook用来监视WM_KEYDOWN and WM_KEYUP音讯,这个音信通过GetMessage or PeekMessage function重回。能够运用那几个Hook来监视输入到音信队列中的键盘新闻。

    钩子函数也足以透过直接再次来到TRUE来甩掉该音信,并阻碍该新闻的传递。不然的话,其余装置了钩子的应用程序将不会收到到钩子的通告同偶尔候还大概有一点都不小可能率爆发不精确的结果。

    (2)对同一事件音讯可安装七个勾子管理进度,这几个勾子管理进度变成了勾子链。当前勾子处理终结后应把勾子音信传递给下三个勾子函数。

    9、WH_KEYBOARD_LL Hook

    钩子在利用完未来必要用UnHookWindowsHookEx(卡塔尔(英语:State of Qatar)卸载,不然会产生麻烦。释放钩子比较轻便,UnHookWindowsHookEx(卡塔尔(قطر‎唯有二个参数。函数原型如下:

    (3)勾子极其是系统勾子会消耗新闻管理时间,裁减系统本性。只有在必要的时候才安装勾子,在接收完结后要登时卸载。

        WH_KEYBOARD_LL Hook监视输入到线程音信队列中的键盘音信。

    UnHookWindowsHookEx

    4、钩子管理函数:public int MyKeyboardProc(int nCode, int wParm, int lParam卡塔尔国

    10、WH_MOUSE Hook

    (

    能够增进自身想要的信息管理(如发邮件,增Gavin件等卡塔尔(قطر‎

        WH_MOUSE Hook监视从GetMessage 大概 PeekMessage 函数重返的鼠标新闻。使用那些Hook监视输入到音讯队列中的鼠标音讯。

          HHOOK hhk;

    新葡亰496net 20新葡亰496net 21这里能够拉长本身想要的新闻管理

    11、WH_MOUSE_LL Hook

    );

            public int MyKeyboardProc(int nCode, IntPtr wParam, IntPtr lParam)
            {
                if (nCode >= 0)
                {
                    KeyBoardHookStruct kbh = (KeyBoardHookStruct)Marshal.PtrToStructure(lParam, typeof(KeyBoardHookStruct));
                    if (kbh.vkCode == (int)Keys.S && (int)Control.ModifierKeys == (int)Keys.Control)  // 截获F8
                    {
                        MessageBox.Show("急速键已拦截!无法保存!");
                        return 1;
                    }
                    if ((int)Control.ModifierKeys == (int)Keys.Delete && (int)Control.ModifierKeys == (int)Keys.Alt && (int)Control.ModifierKeys == (int)Keys.Control)
                    {
                        MessageBox.Show("捕捉到Ctrl Alt Delete");
                        return 1;
                    }
                    if (kbh.vkCode == (int)Keys.Y
                       && (int)Control.ModifierKeys == (int)Keys.Control   (int)Keys.Alt)  //截获Ctrl Alt Y
                    {
                        About msg = new About();
                        msg.Show();
                        MessageBox.Show("不能够一切保留!");
                        return 1;
                    }
                    if (kbh.vkCode == (int)Keys.A)
                    {
                        MessageBox.Show("A");
                        this.label1.Text  = "A";
                    }
                    if (kbh.vkCode == (int)Keys.B)
                    {
                        MessageBox.Show("B");
                        this.label1.Text  = "B";
                    }
                    if (kbh.vkCode == (int)Keys.Enter)
                    {
                        this.label1.Text = "实行成功!";
                    }
                    if (kbh.vkCode == (int)Keys.Back)
                    {
                        this.label1.Text = this.label1.Text.Remove(this.label1.Text.Length - 1);
                    }
                    if (kbh.vkCode == (int)Keys.D1)
                    {
                        this.label1.Text  = "1";
                    }
                }
                return CallNextHookEx(hHook, nCode, wParam, lParam);
            }

        WH_MOUSE_LL Hook监视输入到线程音讯队列中的鼠标新闻。

    函数成功重临TRUE,不然重回FALSE。

     

    12、WH_MSGFILTER 和 WH_SYSMSGFILTER Hooks

    3、一些运维机制:

    留神:若是回去1,则结束消息,这一个新闻到此截止,不再传递。就算重返0或调用CallNextHookEx函数则新闻出了这些钩子继续往下传递,也正是传给音讯着实的选择者.

        WH_MSGFILTER 和 WH_SYSMSGFILTE福特ExplorerHooks使我们能够监视菜单,滚动条,音讯框,对话框新闻还要发掘客商接纳ALT TAB or ALT ESC 组合键切换窗口。WH_MSGFILTE途睿欧Hook只好监视传递到菜单,滚动条,新闻框的新闻,以致传递到通过安装了Hook子程的应用程序建构的对话框的新闻。WH_SYSMSGFILTE凯雷德Hook监视全体应用程序音信。
        
        WH_MSGFILTER 和 WH_SYSMSGFILTELacrosseHooks使大家得以在情势循环时期过滤新闻,那等价于在主消息循环中过滤音信。
        
    通过调用CallMsgFilter function能够平昔的调用WH_MSGFILTEOdysseyHook。通过使用这么些函数,应用程序能够在形式循环时期选用同样的代码去过滤音信,就像在主消息循环里相仿。

    在Win16碰到中,DLL的大局数据对种种载入它的经过来讲都是相似的;而在Win32情形中,景况却产生了变动,DLL函数中的代码所创办的其他对象(富含变量)都归调用它的线程或进程具备。当进程在载入DLL时,操作系统自动把DLL地址映射到该进程的民用空间,也便是经过的虚构地址空间,何况也复制该DLL的全局数据的一份拷贝到该进程空间。也便是说各类进程所具有的平等的DLL的全局数据,它们的名号风度翩翩致,但其值却并不一定是千篇风华正茂律的,並且是互不干涉的。

     //键盘Hook布局函数(详细的情况查看msdn的Platform SDK中的KBDLLHOOKSTRUCT构造卡塔尔

    13、WH_SHELL Hook

    故此,在Win32条件下要想在多个经过中国共产党享数据,就非得举行供给的安装。在拜望同叁个Dll的各进程之间共享存款和储蓄器是经过存款和储蓄器映射文件技巧实现的。也足以把那些供给分享的数量分离出来,放置在叁个单独的数目段里,并把该段的习性设置为分享。必需给这一个变量赋初值,不然编写翻译器会把未有赋早先值的变量放在三个叫未被开头化的多少段中。

            [StructLayout(LayoutKind.Sequential)]
            public class KeyBoardHookStruct
            {
                public int vkCode;//表明一个在1到254间的设想键盘码
                public int scanCode;//表示硬件扫描码
                public int flags;
                public int time;
                public int dwExtraInfo;
            }

        外壳应用程序能够行使WH_SHELL Hook去采用首要的文告。当外壳应用程序是激活的还要当顶层窗口创立恐怕灭亡时,系统调用WH_SHELL Hook子程。
      WH_SHELL 共有5钟情況:

    #pragma data_seg预管理指令用于安装分享数据段。比如:

    5、钩子函数实行三回的解决办法:

    1. 若是有个top-level、unowned 窗口被爆发、起效能、或是被摧毁;
    2. 当Taskbar须求重画有个别开关;
    3. 当系统须要出示关于Taskbar的三个前后相继的最小化情势;
    4. 当近来的键盘结构意况退换;
    5. 当使用者按Ctrl Esc去实践Task Manager(或同拔尖别的程序)。

    #pragma data_seg("SharedDataName")

    最终,迎接朋友们张开指正,多谢!

        根据规矩,外壳应用程序都不收受WH_SHELL音信。所以,在应用程序能够选择WH_SHELL音信此前,应用程序必得调用SystemParametersInfo function注册它协和。

    HHOOK hHook=NULL;

     Best Reagards,

    #pragma data_seg()

    Charles Chen

    在#pragma data_seg("SharedDataName")和#pragma data_seg(卡塔尔之间的具备变量将被访谈该Dll的具有进度见到和分享。再加上一条指令#pragma comment(linker,"/section:.SharedDataName,rws"卡塔尔,那么这些数据节中的数据足以在富有DLL的实例之间分享。全部对那个数据的操作都指向同多少个实例的,并不是在各个进程之处空间中都有生机勃勃份。

     

    当进度隐式或显式调用二个动态Curry的函数时,系统都要把那个动态库映射到这么些历程的虚构地址空间里(以下简单称谓"地址空间"卡塔尔(قطر‎。那使得DLL成为进度的意气风发有个别,以那几个进程的地位推行,使用那几个历程的货仓。

    4、系统钩子与线程钩子:

    SetWindowsHookEx(卡塔尔(قطر‎函数的结尾三个参数决定了此钩子是系统钩子依旧线程钩子。

    线程勾子用于监视钦定线程的风云新闻。线程勾子常常在近年来线程大概当前线程派生的线程内。

    系统勾子监视系统中的所有线程的平地风波音信。因为系统勾子会耳闻则诵系统中负有的应用程序,所以勾子函数务必放在独立的动态链接库(DLL)中。系统活动将含有"钩子回调函数"的DLL映射到受钩子函数影响的具备进度之处空间中,将要这几个DLL注入了那个经过。

    几点表明:

    (1)假如对于同样事件(如鼠标新闻)既安装了线程勾子又安装了系统勾子,那么系统会活动先调用线程勾子,然后调用系统勾子。

    (2)对雷同事件音讯可安装多个勾子管理进程,这么些勾子管理进度造成了勾子链。当前勾子管理终结后应把勾子消息传递给下八个勾子函数。

    (3)勾子非常是系统勾子会损耗音讯管理时间,降低系统质量。唯有在必要的时候才安装勾子,在利用完成后要立马卸载。

    钩子的门类:

    每豆蔻梢头种档案的次序的Hook能够使应用程序能够监视不一致门类的系统音讯管理体制。上面描述全数能够接纳的Hook类型。

    1、WH_CALLWNDPROC和WH_CALLWNDPROCRET Hooks

    WH_CALLWNDPROC和WH_CALLWNDPROCRET Hooks使您能够监视发送到窗口进度的新闻。系统在音信发送到选用窗口进程早先调用WH_CALLWNDPROC Hook子程,况且在窗口进度处理完音讯之后调用WH_CALLWNDPROCRET Hook子程。

    WH_CALLWNDPROCRET Hook传递指针到CWPRETSTRUCT构造,再传递到Hook子程。

    CWPRETSTRUCT构造包罗了来自管理音信的窗口进度的重临值,雷同也包罗了与那个消息关联的音讯参数。

    2、WH_CBT Hook

    在以下事件以前,系统都会调用WH_CBT Hook子程,这么些事件包涵:

    1. 激活,构造建设,销毁,最小化,最大化,移动,改动尺寸等窗口事件;

    2. 完了系统指令;

    3. 根源系统新闻队列中的移动鼠标,键盘事件;

    4. 安装输入核心事件;

    5. 一起系统音信队列事件。

    Hook子程的再次来到值鲜明系统是还是不是允许或许防守那么些操作中的一个。

    3、WH_DEBUG Hook

    在系统调用系统中与别的Hook关联的Hook子程早先,系统会调用WH_DEBUG Hook子程。你可以运用那些Hook来调整是或不是同意系统调用与其他Hook关联的Hook子程。

    4、WH_FOREGROUNDIDLE Hook

    当应用程序的前台线程处于空闲状态时,能够应用WH_FOREGROUNDIDLE Hook推行低优先级的天职。当应用程序的前台线程大致要产生空闲状态时,系统就能够调用WH_FOREGROUNDIDLE Hook子程。

    5、WH_GETMESSAGE Hook

    应用程序使用WH_GETMESSAGE Hook来监视从GetMessage or PeekMessage函数重返的音讯。你能够接收WH_GETMESSAGE Hook去监视鼠标和键盘输入,甚至任何发送到音讯队列中的音信。

    6、WH_JOURNALPLAYBACK Hook

    WH_JOUWranglerNALPLAYBACK Hook使应用程序能够插入音讯到系统新闻队列。基本上能用这几个Hook重放通过运用WH_JOU帕杰罗NALRECO昂科威D Hook记录下来的连年的鼠标和键盘事件。只要WH_JOU福特ExplorerNALPLAYBACK Hook已经安装,符合规律的鼠标和键盘事件正是于事无补的。

    WH_JOUPAJERONALPLAYBACK Hook是全局Hook,它无法象线程特定Hook雷同使用。

    WH_新葡亰496net,JOULANDNALPLAYBACK Hook重临超时值,那一个值告诉系统在拍卖来自重放Hook当前新闻以前须要等待多久(皮秒)。这就使Hook能够调节实时事件的重播。

    WH_JOULANDNALPLAYBACK是system-wide local hooks,它们不会被注入到其余路程地址空间。

    7、WH_JOURNALRECORD Hook

    WH_JOU凯雷德NALRECO牧马人D Hook用来监视和记录输入事件。规范的,可以选择那些Hook记录一而再的鼠标和键盘事件,然后通过使用WH_JOURNALPLAYBACK Hook来回放。

    WH_JOU君越NALRECO汉兰达D Hook是大局Hook,它不可能象线程特定Hook同样使用。

    WH_JOU中华VNALRECO普拉多D是system-wide local hooks,它們不會被注射到别的路程位址空間。

    8、WH_KEYBOARD Hook

    在应用程序中,WH_KEYBOAGL450D Hook用来监视WM_KEYDOWN and WM_KEYUP音讯,这一个消息通过GetMessage or PeekMessage function重返。可以使用这么些Hook来监视输入到信息队列中的键盘音讯。

    9、WH_KEYBOARD_LL Hook

    WH_KEYBOARD_LL Hook监视输入到线程音讯队列中的键盘音信。

    10、WH_MOUSE Hook

    WH_MOUSE Hook监视从GetMessage 也许 PeekMessage 函数重临的鼠标音讯。使用那几个Hook监视输入到新闻队列中的鼠标新闻。

    11、WH_MOUSE_LL Hook

    WH_MOUSE_LL Hook监视输入到线程消息队列中的鼠标音讯。

    12、WH_MSGFILTER 和 WH_SYSMSGFILTER Hooks

    WH_MSGFILTER 和 WH_SYSMSGFILTE奥迪Q5Hooks使大家得以监视菜单,滚动条,信息框,对话框消息还要发掘客户采纳ALT TAB or ALT ESC 组合键切换窗口。WH_MSGFILTEHavalHook只好监视传递到菜单,滚动条,音讯框的消息,甚至传递到通过安装了Hook子程的应用程序建构的对话框的新闻。WH_SYSMSGFILTETiguanHook监视全体应用程序新闻。

    WH_MSGFILTER 和 WH_SYSMSGFILTE途达Hooks使大家得以在方式循环时期过滤音信,那等价于在主音讯循环中过滤音讯。

    经过调用CallMsgFilter function能够一向的调用WH_MSGFILTEMuranoHook。通过行使那个函数,应用程序可以在格局循环时期采取同风度翩翩的代码去过滤新闻,就像是在主音讯循环里相同。

    13、WH_SHELL Hook

    外壳应用程序能够利用WH_SHELL Hook去采取主要的打招呼。当外壳应用程序是激活的同有时候当顶层窗口创建或然消亡时,系统调用WH_SHELL Hook子程。

    WH_SHELL 共有5钟情況:

    1. 若是有个top-level、unowned 窗口被发生、起效果、或是被损毁;

    2. 当Taskbar需求重画有些开关;

    3. 当系统须求显示关于Taskbar的一个顺序的最小化情势;

    4. 当近年来的键盘布局情形改换;

    5. 当使用者按Ctrl Esc去实行Task Manager(或同品品级的前后相继)。

    依据惯例,外壳应用程序都不抽取WH_SHELL音信。所以,在应用程序能够收到WH_SHELL音讯早先,应用程序必需调用SystemParametersInfo function注册它本人。

    在运用钩未时,首要的流水生产线是:

    1、安装(或叫注册)钩子。

    2、如若想让捕获的Windows消息持续往下传递,则要调用CallNextHookEx函数,指向钩子链表中的下叁个子程(可能叫做回调函数。)。

    3、使用完钩子要登时地卸载钩子,不然大概会抓住错误。

    非常少说了,贴上自身的代码:

    新葡亰496net 22新葡亰496net 23View Code

      1 using System;
      2 using System.Collections.Generic;
      3 using System.Linq;
      4 using System.Runtime.InteropServices;
      5 using System.Text;
      6 using System.Windows.Forms;
      7 using System.Text.RegularExpressions;
      8 namespace HookUtility
      9 {
     10     internal enum HookType
     11     {
     12         MsgFilter = -1,
     13         JournalRecord = 0,
     14         JournalPlayback = 1,
     15         Keyboard = 2,
     16         GetMessage = 3,
     17         CallWndProc = 4,
     18         CBT = 5,
     19         SysMsgFilter = 6,
     20         Mouse = 7,
     21         Hardware = 8,
     22         Debug = 9,
     23         Shell = 10,
     24         ForegroundIdle = 11,
     25         CallWndProcRet = 12,
     26         KeyboardLL = 13,
     27         MouseLL = 14
     28     }
     29     internal delegate IntPtr HookProc(int code, IntPtr wparam, IntPtr lparam);
     30     public class GlobalHook
     31     {
     32         private IntPtr m_NextHookPtr = IntPtr.Zero;
     33         private IntPtr m_Handle = IntPtr.Zero;
     34         private IntPtr _handle = IntPtr.Zero;
     35         [DllImport("kernel32.dll")]
     36         internal extern static int GetCurrentThreadId(); //获取当前线程ID
     37         [DllImport("User32.dll")]
     38         internal extern static void UnhookWindowsHookEx(IntPtr handle); //卸载线程钩子
     39         [DllImport("User32.dll")]
     40         internal extern static IntPtr SetWindowsHookEx(int idHook, [MarshalAs(UnmanagedType.FunctionPtr)] HookProc lpfn, IntPtr hinstance, int threadID); //安装钩子
     41         [DllImport("User32.dll")]
     42         internal extern static IntPtr CallNextHookEx(IntPtr handle, int code, IntPtr wparam, IntPtr lparam); //获取下一个钩子子程 
     43         [DllImport("kernel32.dll")]
     44         static extern IntPtr LoadLibrary(string lpFileName);//加载库
     45 
     46         public GlobalHook()
     47         {
     48             InstallHook();//安装钩子
     49         }
     50         ~GlobalHook()
     51         {
     52             UnInstallHook();//卸载钩子
     53         }
     54         private void InstallHook()
     55         {
     56             IntPtr hinstance = LoadLibrary("User32");
     57             HookProc hookProc = new HookProc(IdentyFormHookProc);
     58             this.m_NextHookPtr = SetWindowsHookEx((int)HookType.CBT,hookProc,hinstance,GetCurrentThreadId());
     59         }
     60         private void UnInstallHook()
     61         {
     62             if (this.m_NextHookPtr != IntPtr.Zero)
     63             {
     64                 UnhookWindowsHookEx(this.m_NextHookPtr);//卸载钩子
     65             }
     66         }
     67         /// <summary>
     68         /// 监视要素属性查询窗体
     69         /// </summary>
     70         /// <param name="code"></param>
     71         /// <param name="wparam"></param>
     72         /// <param name="lparam"></param>
     73         /// <returns></returns>
     74         private IntPtr IdentyFormHookProc(int code, IntPtr wparam, IntPtr lparam)
     75         {
     76             if (code == 5 && this._handle != wparam)
     77             {
     78                 Control control = Control.FromHandle(wparam);
     79                 if (control != null && control.GetType().FullName == "Test.IdentifyForm")
     80                 {
     81                     _handle = wparam;   // 将窗体句柄记录下来
     82                     foreach (Control item1 in control.Controls)
     83                     {
     84                         if (item1 is PageableListViewControl)
     85                         {
     86                             foreach (Control item2 in item1.Controls)
     87                             {
     88                                 if (item2 is ToolStripContainer&&this.m_Handle==IntPtr.Zero)
     89                                 {
     90                                     ToolStripItem newItem = ((ToolStrip)((ToolStripContainer)item2).BottomToolStripPanel.Controls[0]).Items.Add("测试");
     91                                     newItem.Alignment = ToolStripItemAlignment.Right;
     92                                     newItem.Click  = new EventHandler(newItem_Click);
     93                                     this.m_Handle = item2.Handle;
     94                                 }
     95                             }
     96                         }
     97                         else if (item1 is TreeView)
     98                         {
     99                         }
    100                     }
    101                 }
    102             }
    103             return CallNextHookEx(this.m_NextHookPtr, code, wparam, lparam);//钩子的下一个子程
    104         }
    105 
    106         void newItem_Click(object sender, EventArgs e)
    107         {
    108             if (this.m_HookHelper == null)
    109             {
    110                 MessageBox.Show("失败!");
    111             }
    112         }
    113     }
    114 }
    

    自个儿水平有限,招待各位钻探指正

    本文由新葡亰496net发布于奥门新萄京娱乐场,转载请注明出处:新葡亰496net:三个鼠标钩子实例,动态更新窗体

    关键词: