类型的已垃圾回收委托进行了回调。这可能会导致应用程序崩溃、损坏和数据丢失。向非托管代码传递委托时,托管应用程序必须让这些委托保持活动状态,直到确信不会再次调用它们的问题的解决方法 续集

接上文

今天突然发现键盘控制不行了,结果还是那个问题搞的鬼,原以为解决了,但是紧接着问题又来了,汗颜啊,将钩子封装成dll

前台调用实例如下

CHW.HookHelper hook;  //钩子

<span style="font-family:Microsoft YaHei;font-size:18px;"><span style="font-family:Microsoft YaHei;font-size:18px;">private void MainForm_Activated(object sender, EventArgs e)
        {
            //注册事件
            hook = new CHW.HookHelper();
            hook.SetHook();
            hook.OnKeyDownEvent += new KeyEventHandler(hook_OnKeyDownEvent);
            hook.OnKeyUpEvent += new KeyEventHandler(hook_OnKeyUpEvent);
        }</span></span>
<span style="font-family:Microsoft YaHei;font-size:18px;"><pre name="code" class="csharp">private void MainForm_Leave(object sender, EventArgs e)
        {
            //注销钩子事件
            hook.UnHook();
        }
void hook_OnKeyUpEvent(object sender, KeyEventArgs e)
        {
            if (chkbAllowKeyboard.Checked)
            {
                //按了左键  按了右键  按了上键  按了下键 之后放起操作
                if (e.KeyCode == Keys.Left || e.KeyCode == Keys.Right || e.KeyCode == Keys.Up || e.KeyCode == Keys.Down)
                    btn_MouseUp(sender, null);
            }
        }

        /// <summary>
        /// 钩子程序控制,键盘作用
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void hook_OnKeyDownEvent(object sender, KeyEventArgs e)
        {
            if (chkbAllowKeyboard.Checked)
            {
                if (e.KeyCode == Keys.Left)
                {
                    //按下左键
                    btnLeft.Focus();
                    btnLeft_MouseDown(sender, null);
                }
                if (e.KeyCode == Keys.Right)
                {
                    //按下右键
                    btnRight.Focus();
                    btnRight_MouseDown(sender, null);
                }
                if (e.KeyCode == Keys.Up)
                {
                    //按下上键
                    btnFront.Focus();
                    btnFront_MouseDown(sender, null);
                }
                if (e.KeyCode == Keys.Down)
                {
                    //按下下键
                    btnBack.Focus();
                    btnBack_MouseDown(sender, null);
                }
            }
        }
</span>

然后经过一般搜索查找,方法如下:


<span style="font-family:Microsoft YaHei;font-size:18px;"><pre name="code" class="csharp">private int KeyboardHookProc(int nCode, Int32 wParam, IntPtr lParam)
        {
            try
            {
                //如果该消息被丢弃(nCode<0)或者没有事件绑定处理程序则不会触发事件
                if ((nCode >= 0) && (OnKeyDownEvent != null || OnKeyUpEvent != null || OnKeyPressEvent != null))
                {
                    KeyboardHookStruct KeyDataFromHook = (KeyboardHookStruct)Marshal.PtrToStructure(lParam, typeof(KeyboardHookStruct));
                    Keys keyData = (Keys)KeyDataFromHook.vkCode;

                    //按下控制键
                    if ((OnKeyDownEvent != null || OnKeyPressEvent != null) && (wParam == WM_KEYDOWN || wParam == WM_SYSKEYDOWN))
                    {
                        if (IsCtrlAltShiftKeys(keyData) && preKeysList.IndexOf(keyData) == -1)
                            preKeysList.Add(keyData);
                    }

                    //WM_KEYDOWN和WM_SYSKEYDOWN消息,将会引发OnKeyDownEvent事件
                    if (OnKeyDownEvent != null && (wParam == WM_KEYDOWN || wParam == WM_SYSKEYDOWN))
                    {
                        KeyEventArgs e = new KeyEventArgs(GetDownKeys(keyData));

                        OnKeyDownEvent(this, e);
                    }

                    //WM_KEYDOWN消息将引发OnKeyPressEvent
                    if (OnKeyPressEvent != null && wParam == WM_KEYDOWN)
                    {
                        byte[] keyState = new byte[256];
                        GetKeyboardState(keyState);
                        byte[] inBuffer = new byte[2];
                        if (ToAscii(KeyDataFromHook.vkCode, KeyDataFromHook.scanCode, keyState, inBuffer, KeyDataFromHook.flags) == 1)
                        {
                            KeyPressEventArgs e = new KeyPressEventArgs((char)inBuffer[0]);
                            OnKeyPressEvent(this, e);
                        }
                    }

                    //松开控制键
                    if ((OnKeyDownEvent != null || OnKeyPressEvent != null) && (wParam == WM_KEYUP || wParam == WM_SYSKEYUP))
                    {
                        if (IsCtrlAltShiftKeys(keyData))
                        {
                            for (int i = preKeysList.Count - 1; i >= 0; i--)
                            {
                                if (preKeysList[i] == keyData)
                                    preKeysList.RemoveAt(i);
                            }
                        }
                    }

                    //WM_KEYUP和WM_SYSKEYUP消息,将引发OnKeyUpEvent事件
                    if (OnKeyUpEvent != null && (wParam == WM_KEYUP || wParam == WM_SYSKEYUP))
                    {
                        KeyEventArgs e = new KeyEventArgs(GetDownKeys(keyData));
                        OnKeyUpEvent(this, e);
                    }
                }

               <strong> return CallNextHookEx(hHook, nCode, wParam, lParam);
                //调用下一个钩子函数,如果返回非0,就是丢弃该消息,此时windows不会处理该消息</strong>
                //return 0;
            }
            catch (Exception)
            {
                return 0;
            }
        }
目前测试在Win7+VS2010调试会报错,运行编译后文件没有问题,在XP+VS2010下调试会报错,运行编译后文件没有问题</span>
</pre><pre name="code" class="csharp"><span style="font-family:Microsoft YaHei;font-size:18px;">如果将上述修改为:return 0;则不会出问题,此时只有一个钩子的话就没有问题,如果有多个钩子大于2个以上就会有问题了</span>
</pre><p><span style="font-family:Microsoft YaHei;font-size:18px;"></span></p><p><span style="font-family:Microsoft YaHei;font-size:18px;">上篇文章代码中出现问题的部分代码改成源代码如下:</span></p><p><pre name="code" class="csharp"><span style="font-family:Microsoft YaHei;font-size:18px;">public void SetHook()
        {
            //KeyboardHookDelegate = KeyboardHookProc;
            KeyboardHookDelegate = new HookProc(KeyboardHookProc);
            Process cProcess = Process.GetCurrentProcess();
            ProcessModule cModule = cProcess.MainModule;
            IntPtr intPtr = GetModuleHandle(cModule.ModuleName);
            hHook = SetWindowsHookEx(WH_KEYBOARD_LL, KeyboardHookDelegate, intPtr, 0);
            if (hHook == 0)
            {
                UnHook();
                //throw new Exception(Marshal.GetLastWin32Error().ToString());
            }
        }</span>

时间: 2024-11-15 04:37:09

类型的已垃圾回收委托进行了回调。这可能会导致应用程序崩溃、损坏和数据丢失。向非托管代码传递委托时,托管应用程序必须让这些委托保持活动状态,直到确信不会再次调用它们的问题的解决方法 续集的相关文章

对“XXX::Invoke”类型的已垃圾回收委托进行了回调。这可能会导致应用程序崩溃、损坏和数据丢失。向非托管代码传递委托时,托管应用程序必须让这些委托保持活动状态,直到确信不会再次调用它们

托管调试助手“CallbackOnCollectedDelegate”在“D:\XXX\XXX.vshost.exe”中检测到问题. 其他信息: 对“XXX+HookProc::Invoke”类型的已垃圾回收委托进行了回调.这可能会导致应用程序崩溃.损坏和数据丢失.向非托管代码传递委托时,托管应用程序必须让这些委托保持活动状态,直到确信不会再次调用它们. 经过搜索资料,发现出问题的原因是我的程序里回调函数作用域的问题 (_mouseHookCallBack) 报错前代码: private voi

对“xxx”类型的已垃圾回收委托进行了回调。这可能会导致应用程序崩溃、损坏和数据丢失。向非托管代码传递委托时,托管应用程序必须让这些委托保持活动状态,直到确信不会再次调用它们。 错误解决一例。

最近在写一个海康的门禁的自动监控刷卡事件的程序. 因为用c#写的,大家都知道c#是垃圾自动回收的.海康提供的api是用c++写的,要将处理的回调代码委托给api .刚开始的时候很顺利,但当运行一段时间就会报以下错误: 对“xxx”类型的已垃圾回收委托进行了回调.这可能会导致应用程序崩溃.损坏和数据丢失.向非托管代码传递委托时,托管应用程序必须让这些委托保持活动状态,直到确信不会再次调用它们. 大致的原因是:c#把回调函数资源回收了,导致api收到事件的时候执行回调出错. 网上的解决方案是将回调方

对“demo!demo.Index+HookProc::Invoke”类型的已垃圾回收委托进行了回调。这可能会导致应用程序崩溃、损坏和数据丢失。向非托管代码传递委托时,托管应用程序必须让这些委托保持活

对"demo!demo.Index+HookProc::Invoke"类型的已垃圾回收委托进行了回调.这可能会导致应用程序崩溃.损坏和数据丢失.向非托管代码传递委托时,托管应用程序必须让这些委托保持活动状态,直到确信不会再次调用它们. 解救办法: //保持活动 避免 回调过程 被垃圾回收 GCHandle.Alloc(委托); 对"demo!demo.Index+HookProc::Invoke"类型的已垃圾回收委托进行了回调.这可能会导致应用程序崩溃.损坏和数据丢

C#调用C++函数,类型的已垃圾回收委托进行了回调

由于项目需要,C#需要调用C++的库进行编程. 今天在调试的过程中,突然弹出 ....... 类型的已垃圾回收委托进行了回调.这可能会导致应用程序崩溃.损坏和数据丢失.向非托管代码传递委托时,托管应用程序必须让这些委托保持活动状态,直到确信不会再次调用它们. 这是调用的函数. public delegate void VOICEDATACALLBACKV30(int lVoiceComHandle,IntPtr pRecvDataBuffer, uint dwBufSize, byte byAu

C# ASP.NET Webservice调用外部exe无效的解决方法

最近用asp.net做webservice,其中有个功能是调用执行外部的exe(类似cmd中执行),但执行Process.Start之后就没有结果,同样代码在winform下正常,折腾两天终于找到解决方法 本文参考了以下网页,十分感谢 http://bbs.csdn.net/topics/300053869 http://blog.163.com/[email protected]/blog/static/15737970200862331842368/ 环境:win7 sp1 64位 以及II

64位进程调用32位dll的解决方法 / 程序64位化带来的问题和思考

最近做在Windows XP X64,VS2005环境下做32位程序编译为64位程序的工作,遇到了一些64位编程中可能遇到的问题:如内联汇编(解决方法改为C/C++代码),long类型的变化,最关键的遇到了64位进程需要调用32位dll的问题.由于有一些32位dll没有源代码,无法重新编译为64位dll,所以只能想办法解决64位进程调用32位dll问题,这个问题让我很是挠头了几天. 相关资料:微软公司的官方网站针对这个问题描述如下:在64位的windows系统中,一个64位进程不能加载一个32位

织梦添加超过两百个自定义字段后在使用addfields调用自定义字段出错的解决方法

dedecsm 自定义模型  添加自定义字段(个数一百多个),使用addfields  方法调用,出现调用不出来的情况[addfields  里面就能添加145个字段,多了直接乱码或者无法显示] 解决方法 分别打开 include/dedehtml2.class.php include/dedetag.class.php include/dedetemplate.class.php 搜索 1024 全部改成 10240 文件存储字节改大就可以了. 原文地址:https://www.cnblogs

使用Fragment应用放置后台很久再次进入出现闪退的解决方法

解决办法:在FragmentActivity里oncreate方法判断savedInstanceState==null才生成新Fragment:否则不做处理     @Override     public void onCreate(Bundle savedInstanceState) {         if (savedInstanceState != null) {             savedInstanceState.putParcelable("android:support

window 2008 定时任务调用bat不成功的解决方法

之前一直有在一台XP的机器上调用定时任务.如今这台机器换成了window 2008的操作系统,调用一直不成功.只是在偶然之间攻克了. 选择"任务计划程序" 任务计划程序库 点击创建基本任务 ,名称写上监控数据库.点击下一步 任务触发器  每天,点击下一步 每日填上对应的时间,点击下一步 操作,启动程序,点击下一步 启动程序.程序或脚本中选中须要运行的脚本,在"起始于(可选)"这里一定要填写对应运行程序或是BAT文件的所在文件夹,要不然是运行不成功的. 完毕.