使用元帅类时代码未执行的问题

时间:2019-09-12 10:53:00

标签: c#

我一直在用C#写一个低级的键盘钩子。按下任意键后,效果很好,执行了回调方法,但是如果我尝试在该回调方法中使用诸如Marshal.ReadInt32Marshal.Copy之类的代码,则我的代码将停止在我使用的位置执行Marshal类,就像使用Marshal类一样,它就像一个return语句。

private static IntPtr OnKeyEvent(int code, IntPtr wParam, IntPtr lParam)   
{
    Console.WriteLine("Before");
    int wP = Marshal.ReadInt32(wParam);            
    Console.WriteLine("After");

    return CallNextHookEx(IntPtr.Zero, code, wParam, lParam);
}

其结果是:

Before,Before,Before,Before,Before etc

如果我注释掉Marshal.ReadInt32行:

Before,After,Before,After etc

那是为什么?

2 个答案:

答案 0 :(得分:3)

使用此:

int wP = wParam.ToInt32();

似乎您正在为WH_KEYBOARD_LL或WH_KEYBOARD安装键盘钩。在这种情况下,wParam值包含WM_KEYDOWN(0x0100)或WM_KEYUP(0x0101)-如您所说。您可以从lParam获取虚拟键码-应该是有效的Pointer。因此,您可以将封送功能用于lParam:

int keyCode = Marshal.ReadInt32(lParam);

答案 1 :(得分:1)

您可以检查此操作的正确方式。

https://github.com/Alois-xx/etwcontroller/blob/master/ETWController/Hooking/Hooker.cs

public int KeyboardHook(int nCode, IntPtr wParam, IntPtr lParam)
{
    if (nCode >= 0)
    {
        var keyboardData = (HookNativeDefinitions.KeyboardHookStruct)Marshal.PtrToStructure(lParam, typeof(HookNativeDefinitions.KeyboardHookStruct));
        unchecked
        {
            // wParam is WM_KEYDOWN, WM_KEYUP, WM_SYSKEYDOWN, or WM_SYSKEYUP
            int wInt = wParam.ToInt32();
            var key = KeyInterop.KeyFromVirtualKey((int)keyboardData.vkCode);
            if (wInt == WM.KEYDOWN || wInt == WM.SYSKEYDOWN && OnKeyDown != null)
            {
                OnKeyDown?.Invoke(key);
            }
            else
            {

            }
        }

    }

    return HookNativeDefinitions.CallNextHookEx(MouseHookHandle, nCode, wParam, lParam);
}

您的示例崩溃是因为您尝试取消引用例如(无效*)100 == WM_KEYDOWN用于各种窗口消息。您需要将wParam转换为整数,然后将lParam转换为KeyboardStruct结构,从中获取实际的键码。