事实上现在HOOK是成功的,比如按键的13,右键的7都可以HOOK成功,但是如果去触发,比如我HOOK了记事本的按键,这时候我去记事本中随便键入,就会弹出“数据执行保护”,然后记事本就被结束了,其他的任何程序都是这样啊,要如何解决呢 ?网上能搜到不少.NET的HOOK,但结果都是你复制我的我复制你的,到头来都一样,错都错的一样,哎!而且全是全局HOOK,全局HOOK是不会出错的,但是局部就会,先贴一段代码吧:        IntPtr _nextHookPtr; //记录Hook编号        [DllImport("kernel32.dll")]
        static extern int GetCurrentThreadId(); //取得当前线程编号的API        [DllImport("user32.dll", EntryPoint = "FindWindow", SetLastError = true, CharSet = CharSet.Unicode)]
        static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
        [DllImport("User32.dll")]
        static extern int GetWindowThreadProcessId(IntPtr hwnd, out int ID);
        [DllImport("kernel32.dll")]
        public static extern IntPtr GetModuleHandle(string name);
        [DllImport("User32.dll")]
        internal extern static void UnhookWindowsHookEx(IntPtr handle); //取消Hook的API
        [DllImport("User32.dll")]        internal extern static IntPtr SetWindowsHookEx(int idHook, [MarshalAs(UnmanagedType.FunctionPtr)] HookProc lpfn, IntPtr hinstance, int threadID); //设置Hook的API
        [DllImport("User32.dll")]        internal extern static IntPtr CallNextHookEx(IntPtr handle, int code, IntPtr wparam, IntPtr lparam); //取得下一个Hook的API        public delegate IntPtr HookProc(int code, IntPtr wparam, IntPtr lparam);
private void Form1_Load(object sender, EventArgs e)
        {
            IntPtr txt = FindWindow(null, "无标题 - 记事本");
            if (txt.ToInt32() == 0)
            {
                MessageBox.Show("Null");
                return;
            }
            int threadID = GetWindowThreadProcessId(txt, out threadID);
            SetHook(threadID);
        }
        IntPtr MyHookProc(int code, IntPtr wparam, IntPtr lparam)
        {
            //if (wparam.ToInt32() == 98 || wparam.ToInt32() == 66) //如果用户输入的是 b
            //{
            //    this.textBox1.Text = "a";
            //    return (IntPtr)1; //直接返回了,该消息就处理结束了
            //}
            return CallNextHookEx(_nextHookPtr, code, wparam, lparam);
        }
        public void SetHook(int threadID)
        {
            if (_nextHookPtr != IntPtr.Zero) //已经勾过了
                return;
            HookProc myhookProc = new HookProc(MyHookProc); //声明一个自己的Hook实现函数的委托对象
            _nextHookPtr = SetWindowsHookEx((int)HookType.WH_KEYBOARD_LL, myhookProc, GetModuleHandle(Process.GetCurrentProcess().MainModule.ModuleName), threadID); //加到Hook链中
            MessageBox.Show(_nextHookPtr.ToInt32().ToString());
        }大概的就是这样,HOOK是成功的,但触发了HOOK的时候,被HOOK的程序就会崩溃。

解决方案 »

  1.   


    纯C#钩子实现及应用
    来源:  日期:2006-03-26  我要评论  胶粘剂 结构胶 硅胶 密封胶 中国胶粘剂网
    关于钩子 请参见微软中国社区中《 HOOK专题 》一文。 纯C#钩子(Hook)实现 要实现系统钩子其实很简单,调用三个Win32的API即可。 SetWindowsHookEx 用于设置钩子。(设立一道卡子,盘查需要的信息) [DllImport( " user32.dll " ,CallingConvention = CallingConvention 
    关于钩子
    请参见微软中国社区中《HOOK专题》一文。纯C#钩子(Hook)实现要实现系统钩子其实很简单,调用三个Win32的API即可。
    SetWindowsHookEx 用于设置钩子。(设立一道卡子,盘查需要的信息)        [DllImport( "user32.dll", CallingConvention = CallingConvention.StdCall )]
            public static extern IntPtr SetWindowsHookEx ( WH_Codes idHook, HookProc lpfn,
                IntPtr pInstance, int threadId );CallNextHookEx 用于传递钩子(消息是重要的,所以从哪里来,就应该回到哪里去,除非你决定要封锁消息)        [DllImport( "user32.dll", CallingConvention = CallingConvention.StdCall )]
            public static extern int CallNextHookEx ( IntPtr pHookHandle, int nCode,
                Int32 wParam, IntPtr lParam );UnhookWindowsHookEx 卸载钩子(卸载很重要,卡子设多了会造成拥堵)        [DllImport( "user32.dll", CallingConvention = CallingConvention.StdCall )]
            public static extern bool UnhookWindowsHookEx ( IntPtr pHookHandle );在《HOW TO:在 Visual C# .NET 中设置窗口挂钩》一文中有如下描述: 在 .NET 框架中不支持全局挂钩
    您无法在 Microsoft .NET 框架中实现全局挂钩。若要安装全局挂钩,挂钩必须有一个本机动态链接库 (DLL) 导出以便将其本身插入到另一个需要调入一个有效而且一致的函数的进程中。这需要一个 DLL 导出,而 .NET 框架不支持这一点。托管代码没有让函数指针具有统一的值这一概念,因为这些函数是动态构建的代理。网上查找了很多代码,大都另外包含了一个C++的DLL,用于标识包含lpfn所指的子程的DLL,似乎也验证了这一说法。但实际上并非如此,使用如下代码即可实现全局钩子:
    IntPtr pInstance = Marshal.GetHINSTANCE( Assembly.GetExecutingAssembly().ManifestModule );
    Win32API.SetWindowsHookEx( WH_MOUSE_LL,m_MouseHookProcedure, pInstance, 0 );注:ManifestModule属性是.Net Framework 2.0中新增加的,所以当你依然使用.Net Framework 1.x的时候,可以使用GetModules方法获取当前程序集的所有模块,然后用其中的一个作为GetHINSTAN方法的参数,来获得合适的句柄指针。 钩子应用DEMO-屏幕放大器 点击下载可执行文件(Shift + Esc 退出程序)
    点击下载源文件所谓屏幕放大器,类似与WINDOWS系统中的辅助工具中的放大镜。
    前两天在找资料的时候突然发现在2.0中,Graphics类多了一个CopyFromScreen方法,可以直接实现屏幕抓取,于是有了做屏幕放大器的想法。首先我定义了是SKHOOK类,来截取键盘及鼠标。
    由于需要获得全局的鼠标消息来确定截屏位置,同时要建立一个全局的快捷键来退出程序,所以只能用上面说的钩子来实现。然后我通过鼠标点来设置采样区域,以及窗体的位置。
    采样区域为鼠标点为中心的50*50的矩形区域。窗体位置只实现了简单的鼠标跟随,同时保证了和采样区域不重叠。另外我使用了一个BackgroundWorker来定时刷新更新窗体。主要是为了实现动画内容(GIF、Flash等)的显示。至于移动的时候使用SetWindowPos,主要是为了保证窗体一直位于顶层,否则的话一些置顶的窗口(如QQ)等将覆盖当前窗口。已知问题:
    1。不支持视频截取
    2。部分ToolTip提示无法显示
    3。可能会造成背景窗口部分显示失效。
    4。SKHook类中,对于键盘事件处理,存在不足。还有一个问题,就是当鼠标移动比较快的时候,窗口边框会有残影,不知道是什么原因。这个问题在以往的Fram窗体中一直是困扰我的问题,至今没有找到解决的办法。 http://www.souzz.net/html/edu/net/net7/11518.html
      

  2.   


    拿到句柄了,接下来你要干啥,能否整理一下是要屏蔽输入字符?那应该是查看messagesend,为什么要做热键?
      

  3.   

    看了一下,感觉不一样,无法解释为什么会出错,我的HOOK钩子是可以勾入的,没问题,但是之后去触发,被HOOK的程序就出错,挂掉了
      

  4.   

    做什么都没用,不管做什么都挂掉,即使MyHookProc里面没有代码,也会出错,这似乎是WINDOWS的安全机制导致的?会弹出“数据执行保护”,警告说您的程序不安全,需要关闭,然后被HOOK的程序就挂掉了
    我现在只是想HOOK,比如HOOK记事本的右键,并不想往记事本里面去写什么内容或者读什么……
      

  5.   

    可以看看吗?我只是想了解一下,我搜索到了N年前CSDN的一个帖子也是说这个问题的,但是仍然没有解决。
      

  6.   

    其实就是几个API函数而已……
      

  7.   

    http://topic.csdn.net/u/20100303/16/af3e5eb7-715b-4c96-b994-c58ced3c6006.html
      

  8.   

    晕~你还真是,不愿意发出来就说嘛,算了也不问你要了,更何况是全局的,我都说了全局的我HOOK成功,而且也不会出错,我现在是局部HOOK,我就比如说我要HOOK记事本的右键,或者输入,只要记事本其他的不要,现在HOOK是成功的,返回不是0,但是如果触发了HOOK,记事本就会挂掉,其他的程序也一样,计算器啊之类的,明白了吗?
      

  9.   

    MessageBox.Show 的开销很大的,不如考虑OutputDebugString
      

  10.   

    以前见过这样的问题,我找找。好像是要把HooksProc函数调用方式声明为 CALLBACK。否则容易崩溃
      

  11.   

    曾经见过的帖子:HOOKPROC类型的函数调用形式是:LRESULT CALLBACK CallWndProc(
        int nCode,
        WPARAM wParam,
        LPARAM lParam
    );
    把你的HooksProc函数调用方式声明为 CALLBACK。否则一般默认的将是__cdecl,并非是 HOOKPROC 类型的回调函数。 保证 SetWindowsHookEx 后两个参数绝对不能同时为零。 
    而且这里面很关键的是,由其它进程创建的线程的ID是不能传到这里面的。因为不同进程的线程管理是独立的。 
    这个可能是问题所在。 
    在你的例子中,请将SetWindowsHookEx 最后一个参数指定为 0 这里有一个处理 keyboard 的CallWndProc的例子,你的HooksProc函数可以参考一下 
    这不是一个完整的例子,写下来仅提供思路 :typedef struct _MYHOOKDATA 

        int nType; 
        HOOKPROC hkprc; 
        HHOOK hhook; 
    } MYHOOKDATA; 
     
    MYHOOKDATA myhookdata[NUMHOOKS]; LRESULT CALLBACK KeyboardProc(int nCode, WPARAM wParam, LPARAM lParam) 

        CHAR szBuf[128]; 
        HDC hdc; 
        static int c = 0; 
        size_t cch; 
        size_t * pcch;
        HRESULT hResult;
     
        if (nCode < 0)  // do not process message 
            // 用于指示消息链传递下去,注意你指定的是WH_CALLWNDPROC
            // 它将在系统通知目标之前截获该消息,去掉这句将阻止系统通知的目标收到消息
            return CallNextHookEx(myhookdata[KEYBOARD].hhook, nCode, 
                wParam, lParam); 
     
        hdc = GetDC(hwnd);
        hResult = StringCchPrintf(szBuf, 128/sizeof(TCHAR), "KEYBOARD - nCode: %d, vk: %d, %d times ", nCode, wParam, c++);
        if (FAILED(hResult))
        {
        // TODO: write error handler
        } 
        hResult = StringCchLength(szBuf, 128/sizeof(TCHAR), pcch);
        if (FAILED(hResult))
        {
        // TODO: write error handler
        } 
        TextOut(hdc, 2, 115, szBuf, *pcch); 
        ReleaseDC(hwnd, hdc); 
        return CallNextHookEx(myhookdata[KEYBOARD].hhook, nCode, wParam, 
            lParam); 
    }
      

  12.   

    SetWindowsHookEx 最后一个参数指定为 0 就变成全局了啊……我只是想HOOK单个程序
      

  13.   

    你也只能去多试试了
    http://hi.baidu.com/lysoncn/blog/item/61458c8f91e522e9f11f3630.html
      

  14.   

    [Quote=引用 4 楼 battlerxange 的回复:]
    引用 2 楼 icdbow 的回复:
    拿到句柄了,接下来你要干啥,能否整理一下是要屏蔽输入字符?那应该是查看messagesend,为什么要做热键?做什么都没用,不管做什么都挂掉,即使MyHookProc里面没有代码,也会出错,这似乎是WINDOWS的安全机制导致的?会弹出“数据执行保护”,警告说您的程序不安全,需要关闭,然后被HOOK的程序就挂掉了
    我现在只是想HOOK……