7

現在、キーをテキストボックスに記録するため、安全です。

問題問題は、これを仮想マシンまたは友人のラップトップで実行すると、一定量のキー(ランダム)を押した後にハングすることです。私の場合は完全に正常に実行されます。

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
4

1 に答える 1

10

「CallbackOnCollectedDelegate」MDAをオンにしてアプリケーションをデバッグしてみてください(「デバッグ」->「例外」->「マネージドデバッグアシスタント」->「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;
于 2010-08-22T10:39:00.387 に答える