Windows Hooks 不会触发事件并且 Windows 开始滞后。 (在 C# 中使用 globalmousekeyhook)

Posted

技术标签:

【中文标题】Windows Hooks 不会触发事件并且 Windows 开始滞后。 (在 C# 中使用 globalmousekeyhook)【英文标题】:Windows Hooks do not trigger events and windows starts lagging. (Using globalmousekeyhook in C#) 【发布时间】:2021-06-03 18:35:25 【问题描述】:

我目前与Steelseries GameSense SDK 合作,为我的键盘和鼠标制作自己的效果等。

为了在点击和按下时点亮我的鼠标和键盘,我使用了globalmousekeyhook 库。

很遗憾,鼠标和键盘事件没有被触发。

另外,我的鼠标开始滞后,键盘输入延迟。

滞后和延迟只停留半分钟左右。

我怀疑 windows 删除了钩子,因为它检测到了滞后。

我也尝试了this example program,那里一切正常。

代码如下:

private static readonly IKeyboardMouseEvents GlobalHook = Hook.GlobalEvents();
static InputManager()

    Logger.Log("Starting...", Logger.Type.Info);
    GlobalHook.KeyDown += KeyEvent;
    GlobalHook.MouseDownExt += MouseEvent;
    Logger.Log("Ready!", Logger.Type.Info);

以及事件函数:

private static void KeyEvent(object sender, KeyEventArgs eventArgs)

    Logger.Log(eventArgs.KeyCode.ToString());

private static void MouseEvent(object sender, MouseEventArgs eventArgs)

    Logger.Log(eventArgs.Button.ToString());

你可以找到整个班级(和项目)here。

构造函数是程序中唯一被执行的东西。

关于延迟,我发现事件函数必须很快。在我的情况下这不是问题,因为Logger.Log() 函数很快,并且在使用Console.WriteLine() 时也会出现滞后。

正如我所说,示例程序运行良好。我尝试复制示例代码,但这没有任何区别。我的程序和示例程序之间唯一真正的区别是示例使用.Net Core,但我使用.Net Framework (4.8)。这可能是原因吗?如果是这个原因,有没有办法将这个库与 .Net Framework 一起使用? 我期待任何帮助。

【问题讨论】:

如果您尝试响应所有事件是正常的。您可以尝试登录一个新线程,但它也会使用不必要的系统资源。 private static void KeyEvent(object sender, KeyEventArgs eventArgs) Task.Run(() => Logger.Log(eventArgs.KeyCode.ToString()); ); @OlivierRogier 当我注释掉 Logger.Log() 并因此清空事件函数时,它甚至会滞后。同样不幸的是,链接的包装器不适合我的情况,因为我需要挂钩所有事件。 @aliassce 我尝试了您的建议,但仍然滞后。我链接的example 也记录了所有事件,但由于某种原因它并没有滞后。 Console.ReadLine in Program.Main() 正在阻止一切,无论如何您都没有运行消息循环,所以我不确定您期望发生什么。请注意,您提供的示例代码非常不同,它使用Application.Run(new ApplicationContext()); 设置了一个消息循环我必须说我不明白为什么InputManager.Start 是空的并且所有连接代码都在静态构造函数。这听起来不太安全。 @Charlieface 我现在没有消息循环,因为我首先需要让鼠标和键盘挂钩工作。我希望控制台输出带有我单击的键或鼠标按钮(您可以在 KeyEventMouseEvent 函数中看到)。在调用任何其他方法之前调用静态构造函数。因此,当您调用 InputManager.Start() 时,它会运行构造函数。这样做的好处是,即使您调用类的任何方法,也会调用“start”函数。你能解释一下为什么Console.ReadLine() 会阻塞吗?是否有其他方法可以保持程序运行? 【参考方案1】:

有两个问题:

您需要一个消息泵才能接收挂钩消息。为此,您可以使用以下代码,如您链接的示例所示
Application.Run(new ApplicationContext());
您现在尝试在同一个线程上做两件事:泵送消息并等待输入。相反,将它们分成不同的线程:
private static void Main(string[] args)

    Logger.Log("Program started. Welcome.", Logger.Type.Info);
    ////GameSense.Controller.Start();
    new Thread(() => Console.ReadLine()).Start();
            
    InputManager.Start();
    
    Application.Run(new ApplicationContext());
    InputManager.End();
    Application.Exit();  // needed to close down the message pump and end the other thread

【讨论】:

非常感谢!我对标准泵不太熟悉。今天学习了一些新东西! 刚刚检查:我必须在 InputManager.Start() 之后的同一线程中调用 Application.Run(new ApplicationContext())。它只能以这种方式工作。 (例子也是这样) 如果你愿意,你可以这样做,然后将Console.ReadLine 放在另一个线程中。我不认为这有什么不同 实际上只有将两者放在同一个线程上才有效。 Application.Run(new ApplicationContext()) 启动新的标准管道(当我理解正确的时候?)并且 Console.ReadLine() 不会阻塞“旧”管道?它目前在 GitHub 上的工作方式。当我尝试您的代码时,它仍然滞后。 Application.Run 与管道没有任何关系,它会阻止您使用ReadLine

以上是关于Windows Hooks 不会触发事件并且 Windows 开始滞后。 (在 C# 中使用 globalmousekeyhook)的主要内容,如果未能解决你的问题,请参考以下文章

为啥 Stripe 事件不会触发并且不会被 webhook 接收?

UserControl KeyDown 事件不会触发撤销 Windows 应用程序 KeyDown 事件

Redux-Toolkit 和 React Hooks - 存储更改不会触发重新渲染

react hooks之useDebounce useThrottle

使用带有滚动条的任何控件时不会触发 MouseWheel 事件(在 C# Windows 窗体中)

自动化发布-GitLab WEB Hooks 配置