【发布时间】:2018-08-21 10:47:59
【问题描述】:
我正在使用以下代码尝试获取操作系统范围的键盘输入,但没有成功:
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 根本没有被调用。我怀疑它试图只监听一个不存在的表单,而不是在系统范围内运行。
【问题讨论】:
-
SetWindowsHookEx的返回值是多少? -
既然您的应用程序是特定于 Windows 的,为什么还要限制自己使用 .NET Core?
-
所有这些函数在失败时返回
IntPtr.Zero或false。您可以使用throw new Win32Exception()将错误返回转换为可读异常。请注意,至少可以说,来自托管代码的全局挂钩相当棘手(甚至来自非托管代码——SetWindowsHookEx的“备注”部分有 8 个段落是有原因的)。那是在将 .NET Core 投入其中之前。 -
您需要在调用 SetWindowsHookEx 的线程中运行消息循环。在您的代码中,将无限循环
while(true)替换为消息循环。