SetWindowsHookEx在C#.net内核中不工作?

SetWindowsHookEx在C#.net内核中不工作?,c#,windows,winforms,hook,C#,Windows,Winforms,Hook,我正在使用以下代码尝试在没有运气的情况下获取操作系统范围的键盘输入: using System; using System.Diagnostics; using System.Runtime.InteropServices; class InterceptKeys { private const int WH_KEYBOARD_LL = 13; private const int WM_KEYDOWN = 0x0100; private static LowLeve

我正在使用以下代码尝试在没有运气的情况下获取操作系统范围的键盘输入:

using System;

using System.Diagnostics;
using System.Runtime.InteropServices;

class InterceptKeys

{
    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);

        while(true)
            continue;
    }

    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);
            Console.WriteLine(vkCode);
        }

        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根本没有被调用。我怀疑它只是试图监听一个不存在的表单,而不是在系统范围内运行。

低级Windows钩子在内部使用Windows消息传递。调用
SetWindowsHookEx
的线程的末尾必须有消息循环,该循环允许调用
HookCallback
函数。在C++消息循环中,看起来像这样:

MSG msg;
BOOL result;

for (;;)
{
    result = GetMessage(&msg, nullptr, 0, 0);

    if (result <= 0)
    {
        break;
    }

    TranslateMessage(&msg);
    DispatchMessage(&msg);
}
MSG;
布尔结果;
对于(;;)
{
结果=GetMessage(&msg,nullptr,0,0);

如果(P<低级Windows钩子内部使用Windows消息传递),调用<代码> StWistWOSKOKEX < /C>的线程必须有消息循环,它允许调用<代码> HookCallback < /C>函数。C++消息循环中的这个样子:

MSG msg;
BOOL result;

for (;;)
{
    result = GetMessage(&msg, nullptr, 0, 0);

    if (result <= 0)
    {
        break;
    }

    TranslateMessage(&msg);
    DispatchMessage(&msg);
}
MSG;
布尔结果;
对于(;;)
{
结果=GetMessage(&msg,nullptr,0,0);

如果(结果我显然很晚了,但只是希望我能帮忙(如果OP还没有得到他/她所需要的帮助),那么我将发布我的答案

它在MSDN文档中指出,当您想要设置系统范围的钩子时,必须为hMod参数指定一个

包含lpfn指向的钩子过程的DLL的句柄 参数

如果dwThreadId参数为零或指定 由不同进程创建的线程,lpfn参数必须指向 到DLL中的钩子过程

但是,看看这个:

SetWindowsHookEx(2,kbdHookProc,GetModuleHandle(“user32”),0)


kbdHookProc是我的C#winforms应用程序中的一个函数,但我在hMod参数中给出的值是通过GetModuleHandle加载user32.dll获得的hinstance。我正在使用键盘挂钩(WHU键盘)监控capslock、numlock和scroll lock键的锁定。不要问我为什么这样做,它会起作用,或者为什么起作用,因为我不知道,但是,是的,它起作用了!

我显然已经很晚了,但只是希望我能帮上忙(如果OP还没有得到他/她需要的帮助),所以我发布了我的答案

它在MSDN文档中指出,当您想要设置系统范围的钩子时,必须为hMod参数指定一个

包含lpfn指向的钩子过程的DLL的句柄 参数

如果dwThreadId参数为零或指定 由不同进程创建的线程,lpfn参数必须指向 到DLL中的钩子过程

但是,看看这个:

SetWindowsHookEx(2,kbdHookProc,GetModuleHandle(“user32”),0)


kbdHookProc是我的C#winforms应用程序中的一个函数,但我在hMod参数中给出的值是通过GetModuleHandle加载user32.dll获得的hinstance。我正在使用键盘挂钩(WHU键盘)监视capslock、numlock和scroll lock键的锁定。不要问我为什么这样做,它会工作,或者为什么它会工作,因为我不知道,但是,是的,它会工作!

SetWindowsHookEx的返回值是多少?当应用程序特定于windows时,为什么要将自己限制为.NET Core?所有这些函数都会返回n
IntPtr.Zero
false
失败。您可以使用
抛出新的Win32Exception()
将错误返回转换为可读的异常。请注意,托管代码的全局钩子相当棘手,至少可以说(甚至是非托管代码的“备注”)
SetWindowsHookEx
的部分是8段,这是有原因的)。这是在将.NET Core放入混合之前。您需要在调用SetWindowsHookEx的线程中运行消息循环。在代码中,替换无止境循环
,而(true)
带有消息循环。
SetWindowsHookEx
的返回值是多少?当应用程序特定于windows时,为什么要将自己限制为.NET Core?所有这些函数在失败时返回
IntPtr.Zero
false
。您可以使用
抛出新的Win32Exception()
将错误返回转换为可读异常。请注意,至少可以说,托管代码的全局钩子相当棘手(甚至是非托管代码的全局钩子--
SetWindowsHookEx
的“备注”部分是8段,这是有原因的)。这是在将.NET Core放入混合之前。您需要在调用SetWindowsHookEx的线程中运行消息循环。在代码中,用消息循环替换无尽循环
while(true)