它将键记录到文本框当前是安全的。
问题 问题是当我在虚拟机或朋友的笔记本电脑上运行时, 按下一定数量的键(随机)后,它会挂起。我的运行完全正常。
http://i34.tinypic.com/29o1im8.jpg
class GlobalKeyboardHook
{
#region Definition of Structures, Constants and Delegates
public delegate int KeyboardHookProc(int nCode, int wParam, ref GlobalKeyboardHookStruct lParam);
public struct GlobalKeyboardHookStruct
{
public int vkCode;
public int scanCode;
public int flags;
public int time;
public int dwExtraInfo;
}
const int WM_KEYDOWN = 0x100;
const int WM_KEYUP = 0x101;
const int WM_SYSKEYDOWN = 0x104;
const int WM_SYSKEYUP = 0x105;
const int WH_KEYBOARD_LL = 13;
#endregion
#region Events
public event KeyEventHandler KeyDown;
public event KeyEventHandler KeyUp;
#endregion
#region Instance Variables
public List<Keys> HookedKeys = new List<Keys>();
IntPtr hookHandle = IntPtr.Zero;
#endregion
#region DLL Imports
[DllImport("kernel32.dll")]
static extern IntPtr LoadLibrary(string lpFileName);
[DllImport("user32.dll", CharSet = CharSet.Auto,CallingConvention = CallingConvention.StdCall, SetLastError = true)]
static extern IntPtr SetWindowsHookEx(int hookID, KeyboardHookProc callback, IntPtr hInstance, uint threadID);
[DllImport("user32.dll", CharSet = CharSet.Auto,CallingConvention = CallingConvention.StdCall, SetLastError = true)]
static extern bool UnhookWindowsHookEx(IntPtr hookHandle);
[DllImport("user32.dll", CharSet = CharSet.Auto,CallingConvention = CallingConvention.StdCall)]
static extern int CallNextHookEx(IntPtr hookHandle, int nCode, int wParam, ref GlobalKeyboardHookStruct lParam);
#endregion
#region Public Methods
public int hookProc(int nCode, int wParam, ref GlobalKeyboardHookStruct lParam)
{
if (nCode >= 0)
{
Keys key = (Keys)lParam.vkCode;
if (HookedKeys.Contains(key) == true)
{
KeyEventArgs kea = new KeyEventArgs(key);
if ((wParam == WM_KEYUP || wParam == WM_SYSKEYUP) && KeyUp != null)
{
KeyUp(this, kea);
}
else if ((wParam == WM_KEYDOWN || wParam == WM_SYSKEYDOWN) && KeyDown != null)
{
KeyDown(this, kea);
}
if (kea.Handled) return 1;
}
}
return CallNextHookEx(hookHandle, nCode, wParam, ref lParam);
}
public void hook()
{
IntPtr hInstance = LoadLibrary("user32");
hookHandle = SetWindowsHookEx(WH_KEYBOARD_LL, hookProc, hInstance, 0);
}
public void unhook()
{
UnhookWindowsHookEx(hookHandle);
}
#endregion
#region Constructors and Destructors
public GlobalKeyboardHook()
{
hook();
}
~GlobalKeyboardHook()
{
unhook();
}
#endregion
答案 0 :(得分:10)
尝试在打开“CallbackOnCollectedDelegate”MDA的情况下调试应用程序(Debug - &gt; Exceptions - &gt; Managed Debugging Assistants - &gt; check“CallbackOnCollectedDelegate”)。
这里常见的错误是,在设置挂钩后,GC会自动收集挂钩过程的委托(它是作为P / Invoke封送到SetWindowsHookEx
的一部分创建的)。 GC收集代理后,程序在尝试调用回调时崩溃。这也可以解释随机性。
如果这是您的问题,您会看到如下错误:
对垃圾进行了回调 收集了'...'类型的代表。 这可能会导致应用程序崩溃, 腐败和数据丢失。路过时 委托非托管代码,他们必须 被管理者保持活力 申请,直到它得到保证 他们永远不会被召唤。
尝试将您的钩子程序的引用保留为您班级中的成员,例如:
public delegate int KeyboardHookProc(int nCode, int wParam, ref GlobalKeyboardHookStruct lParam);
public int hookProc(int nCode, int wParam, ref GlobalKeyboardHookStruct lParam)
{
// ...
}
public void hook()
{
_hookProc = new KeyboardHookProc(hookProc);
IntPtr hInstance = LoadLibrary("user32");
hookHandle = SetWindowsHookEx(WH_KEYBOARD_LL, _hookProc, hInstance, 0);
}
KeyboardHookProc _hookProc;