我的c#应用程序创建用于处理键盘事件的键盘钩子(许多读卡器,扫描仪和其他POS设备模拟键盘)。 有时我的应用程序会创建没有错误的键盘钩子,但它不是发射事件和处置抛出异常:
System.ComponentModel.Win32Exception(0x80004005):无法删除' app'的键盘挂钩。错误1404:钩子句柄无效
其他日志条目是相同的错误,但它告诉
ERROR_NOT_ALL_ASSIGNED
Source code of library and demo app.
我无法在我的电脑上重现此问题,也不知道我应该调查什么或谷歌。 我知道:
另外,我不熟悉非托管代码并赢得api。我从一些线程获得了这个代码并根据我的需要修改了它,但是在高级抽象上。
Hook ctor:
public GlobalKeyboardHook()
{
_windowsHookHandle = IntPtr.Zero;
_user32LibraryHandle = IntPtr.Zero;
_hookProc = LowLevelKeyboardProc; // we must keep alive _hookProc, because GC is not aware about SetWindowsHookEx behaviour.
_user32LibraryHandle = LoadLibrary("User32");
if (_user32LibraryHandle == IntPtr.Zero)
{
int errorCode = Marshal.GetLastWin32Error();
throw new Win32Exception(errorCode,
$"Failed to load library 'User32.dll'. Error {errorCode}: {new Win32Exception(Marshal.GetLastWin32Error()).Message}.");
}
_windowsHookHandle = SetWindowsHookEx(WH_KEYBOARD_LL, _hookProc, _user32LibraryHandle, 0);
if (_windowsHookHandle == IntPtr.Zero)
{
int errorCode = Marshal.GetLastWin32Error();
throw new Win32Exception(errorCode,
$"Failed to adjust keyboard hooks for '{Process.GetCurrentProcess().ProcessName}'. Error {errorCode}: {new Win32Exception(Marshal.GetLastWin32Error()).Message}.");
}
}
[DllImport("kernel32.dll")]
private static extern IntPtr LoadLibrary(string lpFileName);
[DllImport("USER32", SetLastError = true)]
private static extern IntPtr SetWindowsHookEx(int idHook, HookProc lpfn, IntPtr hMod, int dwThreadId);
Hook dispose:
protected virtual void Dispose(bool disposing)
{
if (disposing)
{
// because we can unhook only in the same thread, not in garbage collector thread
if (_windowsHookHandle != IntPtr.Zero)
{
if (!UnhookWindowsHookEx(_windowsHookHandle))
{
int errorCode = Marshal.GetLastWin32Error();
throw new Win32Exception(errorCode,
$"Failed to remove keyboard hooks for '{Process.GetCurrentProcess().ProcessName}'. Error {errorCode}: {new Win32Exception(Marshal.GetLastWin32Error()).Message}.");
}
_windowsHookHandle = IntPtr.Zero;
// ReSharper disable once DelegateSubtraction
_hookProc -= LowLevelKeyboardProc;
}
}
if (_user32LibraryHandle != IntPtr.Zero)
{
if (!FreeLibrary(_user32LibraryHandle)) // reduces reference to library by 1.
{
int errorCode = Marshal.GetLastWin32Error();
throw new Win32Exception(errorCode,
$"Failed to unload library 'User32.dll'. Error {errorCode}: {new Win32Exception(Marshal.GetLastWin32Error()).Message}.");
}
_user32LibraryHandle = IntPtr.Zero;
}
}
[DllImport("kernel32.dll", CharSet = CharSet.Auto)]
private static extern bool FreeLibrary(IntPtr hModule);
[DllImport("USER32", SetLastError = true)]
private static extern bool UnhookWindowsHookEx(IntPtr hHook);
答案 0 :(得分:2)
如果你在钩子程序中做错了什么,Windows会在不告诉你的情况下解开你。
LowLevelKeyboardProc
中,您没有检查nCode
!如果nCode
是< CallNextHookEx
,则必须先执行此操作。 0 必须返回LowLevelHooksTimeout
而不进行任何其他处理。您可以尝试在有问题的系统上设置/更改service.center.ts
注册表值,看看是否有帮助。