我们有一些全球键盘挂钩,通过安装 SetWindowsHookExWH_KEYBOARD_LL 出现的随机获得解开的窗户。

我们证实他们的挂钩是不再连接的,因为叫 UnhookWindowsHookEx 在处理返回 false.(还证实,它返回 true 当它是正常工作)

似乎没有以一致的重现,我听说他们可以摆脱钩,由于超时或例外的情况越来越引发的,但是我已经尝试都只是让它坐在一个断点的处理方法对于有超过一分钟,以及只是扔一个随机的异常(C#),它仍然出现工作。

在我们回调我们很快后到另一个线程,以便可能不是问题。我读过有关解决方案,在Windows7设定的超时较高,在登记册,因为Windows7更为积极的有关超时显然是(我们都在运行的windows7资在这里,所以不确定如果发生这种情况在其他操作系统),但这似乎不是一个理想的解决方案。

我认为只是有一个背景线运行刷新钩每隔一段时间,这是予以解决了,但是我不知道有任何真正的负面后果的这样做,而且似乎好于改变一个全球性的窗户注册的设置。

任何其他建议或解决方案? 两类组挂钩和代表他们附着于是静态的,所以他们不应该得到GC。

编辑:核实话 GC.Collect(); 他们仍在工作,因此它们没有得到garbaged收集。

有帮助吗?

解决方案

我觉得这是一个超时问题。

其他开发者已经报道了当它们超过一个(未记录的)的超时值被脱钩低电平钩子Windows7的特定问题。

请参阅该线程对其他开发人员讨论同样的问题。这可能是你需要执行一个繁忙的循环(或慢速垃圾收集),而不是睡眠造成脱钩的行为。在LowLevelKeyboardProc功能断点也可能会造成超时的问题。 (还有的观察,通过另一个任务重的CPU负载可能引起的行为 - 这大概是因为其他任务从LowLevelKeyboardProc功能抢断CPU周期,导致它花费太长的时间)

在该线程中提出的解决方案是尝试在设定的 LowLevelHooksTimeout DWORD在注册表值的 HKEY_CURRENT_USER \控制面板\桌面以一个较大的值。

记住C#的辉煌中的一个是,如果发生了垃圾收集甚至简单的语句可以采取过多的时间量。这(被其他线程或CPU装载)可能解释问题的间歇性。

其他提示

我想到的两件事可能会帮助您找出问题所在。

  1. 为了帮助隔离问题的位置,请运行另一个 WH_KEYBOARD_LL 与当前的钩子同时钩子,并且让它除了沿着钩子链传递数据之外什么都不做。当你发现原来的钩子脱钩时,检查一下这个“虚拟”钩子是否也脱钩了。如果“虚拟”钩子也被脱钩,那么您可以相当肯定问题出在您的钩子之外(即在 Windows 中或与整个进程相关的东西?)如果“虚拟”钩子没有解开,那么问题可能出在你的钩子中的某个地方。

  2. 记录通过回调到达您的钩子的信息并运行它,直到钩子脱钩。重复此操作多次并检查记录的数据,看看是否可以辨别导致脱钩的模式。

我会一次尝试这些,以防万一其中一个会影响其他的结果。如果之后您没有找到问题所在,您可以尝试将它们一起运行。

这是一个长镜头,但以任何机会,你有反病毒软件的运行?这很可能是注意到一个键盘钩子和脚踢出来。

它更可能它会提醒你,并立即将其删除,但它的那些奇怪的事情一个值得一试。

也许别人具有不调用CallNextHookEx方法钩()?

我知道这是一个丑陋的解决方案,但你可以设置一个计时器,直到永远5分钟,然后你可以重新勾你的键盘事件?

我与Win7的机器同样的问题,经过一段时间的键盘钩子正在失去它的参考,我不得不建立一个定时器,每5分钟,又被勾事件,现在它保持它的新鲜。

我使用的以下项目: http://www.codeproject.com/Articles/7294/Processing-Global-Mouse-and-Keyboard-Hooks-in-C 执行任务时某些关键已经压制。

我注意到,在我执行任务的一个键它停下来倾听对于新的按键,然后我改变了KeyboardHookListener静并且它似乎对解决我的问题。我不知道为什么这个解决我的问题,以便随时评论这个!

我热键类:

 class Hotkey
{
    private static KeyboardHookListener _keyboardHookListener;

    public void Start()
    {
        _keyboardHookListener = new KeyboardHookListener(new GlobalHooker()) { Enabled = true };
        _keyboardHookListener.KeyDown += KeyboardListener_OnkeyPress;
    }

    private void KeyboardListener_OnkeyPress(object sender, KeyEventArgs e)
    {
        // Let's backup all projects
        if (e.KeyCode == Keys.F1)
        {
            // Initialize files
            var files = new Files();

            // Backup all projects
            files.BackupAllProjects();
        }
        // Quick backup - one project
        else if (e.KeyCode == Keys.F2)
        {
            var quickBackupForm = new QuickBackup();
            quickBackupForm.Show();
        }
    }
}

很晚但是我想分享的东西。从聚会 在这里, 还有一些提示想把SetWindowsHookEx在一个单独的线程和它的更加一个调度问题。

我还注意到,应用程序。DoEvents是使用相当多的CPU,并发现PeekMessage使用较少。

public static bool active = true;

[StructLayout(LayoutKind.Sequential)]
public struct NativeMessage
{
    public IntPtr handle;
    public uint msg;
    public IntPtr wParam;
    public IntPtr lParam;
    public uint time;
    public System.Drawing.Point p;
}

[SuppressUnmanagedCodeSecurity]
[return: MarshalAs(UnmanagedType.Bool)]
[DllImport("User32.dll", CharSet = CharSet.Auto, SetLastError = true)]
public static extern bool PeekMessage(out NativeMessage message,
    IntPtr handle, uint filterMin, uint filterMax, uint flags);
public const int PM_NOREMOVE = 0;
public const int PM_REMOVE = 0x0001;

protected void MouseHooker()
{
    NativeMessage msg;

    using (Process curProcess = Process.GetCurrentProcess())
    {
        using (ProcessModule curModule = curProcess.MainModule)
        {
            // Install the low level mouse hook that will put events into _mouseEvents
            _hookproc = MouseHookCallback;
            _hookId = User32.SetWindowsHookEx(WH.WH_MOUSE_LL, _hookproc, Kernel32.GetModuleHandle(curModule.ModuleName), 0);
        }
    }
        while (active)
        {
            while (PeekMessage(out msg, IntPtr.Zero,
                (uint)WM.WM_MOUSEFIRST, (uint)WM.WM_MOUSELAST, PM_NOREMOVE))
                ;
            Thread.Sleep(10);
        }

        User32.UnhookWindowsHookEx(_hookId);
        _hookId = IntPtr.Zero;            
}

public void HookMouse()
{
    active = true;
    if (_hookId == IntPtr.Zero)
    {
        _mouseHookThread = new Thread(MouseHooker);
        _mouseHookThread.IsBackground = true;
        _mouseHookThread.Priority = ThreadPriority.Highest;
        _mouseHookThread.Start();
    }
}

所以只是改变的积极bool假,在关闭事件,并呼HookMouse在激活的事件。

禾田

编辑:我注意到游戏是减缓这一点,因此决定脱钩,当应用程序是不活跃的使用活性和关闭事件。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top