全局键盘钩子减慢计算机速度
我正在使用这篇文章中的代码:
private const int WH_KEYBOARD_LL = 13;
private const int WM_KEYDOWN = 0x0100;
private static LowLevelKeyboardProc _proc = HookCallback;
private static IntPtr _hookID = IntPtr.Zero;
public static void Main()
{
_hookID = SetHook(_proc);
//Application.Run();
//UnhookWindowsHookEx(_hookID);
}
private static IntPtr SetHook(LowLevelKeyboardProc proc)
{
using (Process curProcess = Process.GetCurrentProcess())
using (ProcessModule curModule = curProcess.MainModule)
{
return SetWindowsHookEx(WH_KEYBOARD_LL, proc,
GetModuleHandle(curModule.ModuleName), 0);
}
}
private delegate IntPtr LowLevelKeyboardProc(
int nCode, IntPtr wParam, IntPtr lParam);
private static IntPtr HookCallback(
int nCode, IntPtr wParam, IntPtr lParam)
{
if (nCode >= 0 && wParam == (IntPtr)WM_KEYDOWN)
{
int vkCode = Marshal.ReadInt32(lParam);
***custom code***
}
return CallNextHookEx(_hookID, nCode, wParam, lParam);
}
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern IntPtr SetWindowsHookEx(int idHook,
LowLevelKeyboardProc lpfn, IntPtr hMod, uint dwThreadId);
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool UnhookWindowsHookEx(IntPtr hhk);
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern IntPtr CallNextHookEx(IntPtr hhk, int nCode,
IntPtr wParam, IntPtr lParam);
[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern IntPtr GetModuleHandle(string lpModuleName);
经过一些修改,但有时当我按几次击键太快时,计算机会“减慢”一点并变得有点“滞后”。
因此,当它异步触发事件 HookCallback 时,它有时会有点滞后,但我猜它是这个方法“HookCallback”中的代码导致它滞后,还是它自己挂钩?我有一个关于每次输入“HookCallback”时创建一个新线程的想法,这也许会有所帮助,但是我想每次按下一个键时都启动一个新线程吗?我已经收到一个异步调用,所以我不知道除此之外是否应该启动另一个线程。
所以我的问题很简单,它在哪里以及为什么会减慢计算机的速度,是它自己挂钩还是自定义代码?或者我应该将自定义代码放在不同的线程中?
我还有另一个问题,有时按几次按键后“HookCallback”不会被调用,就好像我已经“取消挂钩”事件一样,并且它根本不会捕获任何击键。除非我手动执行,否则如何确保它永远不会取消事件?
谢谢。
I am using the code from this article :
private const int WH_KEYBOARD_LL = 13;
private const int WM_KEYDOWN = 0x0100;
private static LowLevelKeyboardProc _proc = HookCallback;
private static IntPtr _hookID = IntPtr.Zero;
public static void Main()
{
_hookID = SetHook(_proc);
//Application.Run();
//UnhookWindowsHookEx(_hookID);
}
private static IntPtr SetHook(LowLevelKeyboardProc proc)
{
using (Process curProcess = Process.GetCurrentProcess())
using (ProcessModule curModule = curProcess.MainModule)
{
return SetWindowsHookEx(WH_KEYBOARD_LL, proc,
GetModuleHandle(curModule.ModuleName), 0);
}
}
private delegate IntPtr LowLevelKeyboardProc(
int nCode, IntPtr wParam, IntPtr lParam);
private static IntPtr HookCallback(
int nCode, IntPtr wParam, IntPtr lParam)
{
if (nCode >= 0 && wParam == (IntPtr)WM_KEYDOWN)
{
int vkCode = Marshal.ReadInt32(lParam);
***custom code***
}
return CallNextHookEx(_hookID, nCode, wParam, lParam);
}
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern IntPtr SetWindowsHookEx(int idHook,
LowLevelKeyboardProc lpfn, IntPtr hMod, uint dwThreadId);
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool UnhookWindowsHookEx(IntPtr hhk);
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern IntPtr CallNextHookEx(IntPtr hhk, int nCode,
IntPtr wParam, IntPtr lParam);
[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern IntPtr GetModuleHandle(string lpModuleName);
with a little modification but sometimes when i press a couple of keystrokes too fast then the computer "slows" down a bit and gets a little "laggy".
So when it hits asyncronosly the event HookCallback it sometimes get a little laggy, but i guess its the code in this method "HookCallback" that makes it laggy or is it the hooking it self? I had an idea about creating a new thread everytime i enter "HookCallback" , that maybe will help but do i want to start a new thread everytime i press a key? I am getting an asyncronosly call already so i dont know if i should start another thread besides that.
So my question is simple, where and why does it slow down the computer, is it the hooking it self or is it the custom code ? Or should i put the custom code in a different thread?
And i have another question, sometimes after a few keypresses "HookCallback" doesnt get called, as if i have "unhooked" the event, and it wont capture any keystrokes at all. How can i make sure that it never unhooks the event unless i do it in manually?
Thank you.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
我花了相当多的时间做键盘钩子,所以以下只是我自己的经验。 Hook需要要高效。几年前,我编写了一个小型 POS 应用程序,必须捕获击键。它是用 C# 编写的,并且将输入速度减慢到了明显的程度。经过一番头痛之后,我终于意识到巨大的滞后来自于从本机代码到托管代码的转换。我用 C++(原生)重新编写了一小段钩子代码,并看到了我认为“足够好”的改进。
请记住,速度完全取决于您的代码处理它所需的时间。尽最大努力使其高效。
I've spent a fair amount of time doing keyboard hooks, so the following is just my own experience. Hooks need to be efficient. I wrote a small POS app a few years ago that had to capture keystrokes. It was written in C#, and slowed the input to the point of becoming noticeable. After a lot of headaches I finally realized that the big lag was coming from the translation from native code to managed code. I re-wrote small pieces of the hook code in C++ (native) and saw improvements that I would deem "good enough".
Just remember that speed is fully determined by how long your code takes to process it. Try your very best to make it efficient.
关于“脱钩”问题还有另一个因素。如果您的低级全局钩子代码无法在一定时间内完成,操作系统将自动删除您的钩子而不通知您。所以让你的代码运行得尽可能快
干杯
There is another factor about "unhook" problem. If your low level global hook codes can not finish in certain amount of time, the OS will remove your hook automatically without notifying you. So make your codes run as fast as possible
Cheers
如果您只想捕获应用程序中的击键,那么事情会更快;使用
WH_KEYBOARD
而不是WH_KEYBOARD_LL
,这将使性能提升更加明显。If you want to capture keystrokes within your application only, things can be faster then; use
WH_KEYBOARD
instead ofWH_KEYBOARD_LL
, this will make much more noticeable performance increase.我有同样的症状,但事实证明我的问题是由于 Thread.Sleep();
我最近将我的应用程序从控制台更改为 Windows 应用程序。我的代码是:
这使得窗口速度难以置信地,尽管我的钩子所做的只是在使用键盘时增加一个全局变量。当我将其更改为以下内容时,我的滞后问题得到了解决:
I had the same symptoms, but it turned out my issue was due to Thread.Sleep();
I had recently changed my application from a Console to Windows Application. My code had been:
This made windows slow down incredibly, even though all my hook does is increment a global variable whenever the keyboard is used. When I changed it to the following, my lag issue was resolved: