Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/rest/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Keyboard hook 全局键盘挂钩_Keyboard Hook_Setwindowshookex - Fatal编程技术网

Keyboard hook 全局键盘挂钩

Keyboard hook 全局键盘挂钩,keyboard-hook,setwindowshookex,Keyboard Hook,Setwindowshookex,我需要捕获全局键盘消息,因此我将SetWindowsHookEx()与WH_keyboard_LL一起使用。但它只在应用程序处于焦点时工作,并且不会全局触发回调。几乎相同的代码适用于鼠标。LL(使用另一种结构等)请帮助 public const int WH_KEYBOARD_LL = 13; public const int VK_INSERT = 0x2D; public delegate int HookProc(int nCode, IntPtr wParam, IntPtr lPara

我需要捕获全局键盘消息,因此我将SetWindowsHookEx()与WH_keyboard_LL一起使用。但它只在应用程序处于焦点时工作,并且不会全局触发回调。几乎相同的代码适用于鼠标。LL(使用另一种结构等)请帮助

public const int WH_KEYBOARD_LL = 13;
public const int VK_INSERT = 0x2D;
public delegate int HookProc(int nCode, IntPtr wParam, IntPtr lParam);
HookProc KeyboardHookProcedure;

[DllImport("user32.dll", CharSet = CharSet.Auto,
   CallingConvention = CallingConvention.StdCall)]
  public static extern int SetWindowsHookEx(int idHook, HookProc lpfn,
  IntPtr hInstance, int threadId);

[DllImport("user32.dll", CharSet = CharSet.Auto,
   CallingConvention = CallingConvention.StdCall)]
  public static extern bool UnhookWindowsHookEx(int idHook);

[DllImport("user32.dll", CharSet = CharSet.Auto,
   CallingConvention = CallingConvention.StdCall)]
  public static extern int CallNextHookEx(int idHook, int nCode,
  IntPtr wParam, IntPtr lParam);

[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
  private static extern IntPtr GetModuleHandle(string lpModuleName);

[StructLayout(LayoutKind.Sequential)]
  private struct KBDLLHOOKSTRUCT
  {
     public uint vkCode;
     public uint scanCode;
     public uint flags;
     public uint time;
     public IntPtr dxExtraInfo;
  }

private void SetHookKeyboard()
  {
     if (kHook == 0)
     {
        KeyboardHookLL();

        //If the SetWindowsHookEx function fails.
        if (kHook == 0)
        {
           MessageBox.Show("SetWindowsHookEx Failed");
           return;
        }
        button1.Text = "UnHook Windows Hook";
     }
     else
     {
        bool ret = UnhookWindowsHookEx(kHook);
        //If the UnhookWindowsHookEx function fails.
        if (ret == false)
        {
           MessageBox.Show("UnhookWindowsHookEx Failed");
           return;
        }
        kHook = 0;
        this.Text = "Keyboard Hook";
     }
  }

private void KeyboardHookLL()
  {
     KeyboardHookProcedure = new HookProc(MainForm.KeyboardHookProc);
     kHook = SetWindowsHookEx(WH_KEYBOARD_LL, KeyboardHookProcedure,   GetModuleHandle("user32"), 0);
  }

public static int KeyboardHookProc(int nCode, IntPtr wParam, IntPtr lParam)
  {
     KBDLLHOOKSTRUCT MyKeyboardHookStruct = (KBDLLHOOKSTRUCT)Marshal.PtrToStructure(lParam, typeof(KBDLLHOOKSTRUCT));
     if (nCode < 0)
     {
        return CallNextHookEx(hHook, nCode, wParam, lParam);
     }
     else
     {
        Form tempForm = Form.ActiveForm;
        tempForm.Text = MyKeyboardHookStruct.vkCode.ToString();
        if (MyKeyboardHookStruct.vkCode == VK_INSERT)
        {
           MainForm.botAlive = false;
           MessageBox.Show(MainForm.botAlive.ToString());
        }
        return CallNextHookEx(hHook, nCode, wParam, lParam);
     }
  }
public const int WH_键盘LL=13;
公共常量int VK_INSERT=0x2D;
公共委托int-HookProc(int-nCode、IntPtr-wParam、IntPtr-lParam);
HookProc键盘hookprocedure;
[DllImport(“user32.dll”,CharSet=CharSet.Auto,
CallingConvention=CallingConvention.StdCall)]
公共静态外部int SetWindowsHookEx(int idHook、HookProc lpfn、,
IntPtr hInstance,int threadId);
[DllImport(“user32.dll”,CharSet=CharSet.Auto,
CallingConvention=CallingConvention.StdCall)]
公共静态外部bool unhookwindowshookx(intidhook);
[DllImport(“user32.dll”,CharSet=CharSet.Auto,
CallingConvention=CallingConvention.StdCall)]
公共静态外部int CALLNEXTHOKEX(int idHook,int nCode,
IntPtr wParam、IntPtr lParam);
[DllImport(“kernel32.dll”,CharSet=CharSet.Auto,SetLastError=true)]
私有静态外部IntPtr GetModuleHandle(字符串lpModuleName);
[StructLayout(LayoutKind.Sequential)]
私有结构KBDLLHOOKSTRUCT
{
公共uint vkCode;
公共uint扫描码;
国旗;
公共时间;
公共IntPtr dxExtraInfo;
}
私有void SetHookKeyboard()
{
如果(kHook==0)
{
键盘挂钩();
//如果SetWindowsHookEx功能失败。
如果(kHook==0)
{
MessageBox.Show(“SetWindowsHookEx失败”);
返回;
}
button1.Text=“解开Windows挂钩”;
}
其他的
{
bool-ret=unhookwindowshookx(kHook);
//如果UnhookWindowsHookEx函数失败。
如果(ret==false)
{
Show(“UnhookWindowsHookEx失败”);
返回;
}
kHook=0;
this.Text=“键盘挂钩”;
}
}
私有void KeyboardHookLL()
{
KeyboardHookProcedure=新的HookProc(MainForm.KeyboardHookProc);
kHook=setWindowshookx(WH_-KEYBOARD,KeyboardHookProcedure,GetModuleHandle(“user32”),0);
}
公共静态int-KeyboardHookProc(int-nCode、IntPtr-wParam、IntPtr-lParam)
{
KBDLLHOOKSTRUCT MyKeyboardHookStruct=(KBDLLHOOKSTRUCT)Marshal.PtrToStructure(lParam,typeof(KBDLLHOOKSTRUCT));
if(nCode<0)
{
返回CallNextHookEx(hHook、nCode、wParam、lParam);
}
其他的
{
Form tempForm=Form.ActiveForm;
tempForm.Text=MyKeyboardHookStruct.vkCode.ToString();
if(MyKeyboardHookStruct.vkCode==VK_INSERT)
{
MainForm.botAlive=false;
Show(MainForm.botAlive.ToString());
}
返回CallNextHookEx(hHook、nCode、wParam、lParam);
}
}
问题出在“调试”功能中

Form tempForm = Form.ActiveForm;

这要归功于乔恩:

我知道这是一篇老文章,我有点离题了,但我注意到原始代码中有一个险恶的缺陷,它会在适当的时候逆转并严重地伤害你(我知道在我的情况下确实如此):

最好是:

  [DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
   static extern IntPtr SetWindowsHookEx(HookType hookType, HookProc lpfn, IntPtr hMod, uint dwThreadId);
其他签名也应进行类似的更改即使microsoft本身的资源显示SetwindowsHookEx的返回类型为int(),您也不应该轻松地用其他类型替换“IntPtr”。在这种情况下,“int”仅在32位操作系统中等同于“IntPtr”。在64位平台中,“IntPtr”是64位的,而“int”一直只有32位,这就打开了一整罐蠕虫。使用“int”最糟糕的一个方面是,如果SetWindowsHookEx的返回值不能放入其中,那么很可能最终会导致int句柄损坏(这很少见,但并非不可想象)

这意味着,如果应用程序的生存期超过了您解除钩子/处置钩子的时间点(而不是从一开始,解除钩子调用就可以工作…)然后,您可能会完全冻结鼠标和/或键盘,直到主机进程被终止。大多数人只需在此时重新启动计算机,然后完全处理您的应用程序。所有这些“键盘/鼠标冻结”的事情之所以发生,是因为未插入的钩子需要到达主机应用程序的消息泵,这显然是不可能发生的,因为它所属的组件在dispose-wooohoo期间崩溃了


TL;DR:请注意您正在使用的p/invoke方法的签名,尤其是intptr。

一般来说,使用热键而不是挂钩更安全。你需要一个钩子而不是热键有什么特别的原因吗?是的,我需要捕获每个输入,因为它将是一个“记录器”。如果这是主窗体的代码,那么你不应该在某个地方注册eventhandler吗?这是从整个代码中选择的。KeyboardHookProc是一个回调方法,所以我不必注册任何eventhandler。它捕捉键盘输入(但仅当呼叫应用程序处于焦点且我需要它捕捉全局键盘消息时)
  [DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
   static extern IntPtr SetWindowsHookEx(HookType hookType, HookProc lpfn, IntPtr hMod, uint dwThreadId);