我的Hook功能停止工作

时间:2015-10-09 01:57:19

标签: delphi hook global

经过一段时间的崩溃,我不得不重新开始了

KeyboardHook的功能

function KeyboardHook(Code: Integer; wParam : WPARAM; lParam : LPARAM): LongInt;
var
  Buffer: TEventMsg;
  Key: Cardinal;
begin
  if (wParam = $0101) and
     (App.Inside) then
  begin
    Buffer := PEventMsg(lParam)^;
    Key := Buffer.message;

    if App.Inside then
    begin
      case Key of
        VK_NEXT: App.Next;
        VK_CAPITAL: App.Show;
      end;
    end;
  end;
  CallNextHookEx(Hook_ID_Keyboard, Code, wParam, lParam);
  Result := 0;
end;

启动挂钩的功能

function StartHookKeyboard: Boolean; stdcall;
begin
  Hook_ID_Keyboard := SetWindowsHookEx(13, @KeyboardHook, HInstance, 0);
  If Hook_ID_Keyboard = 0  then
    Result := False else
    Result := True;
end;

我的代码中是否有错误?

1 个答案:

答案 0 :(得分:1)

请勿使用硬编码magic numbers。在此上下文中,13为WH_KEYBOARD_LL$0101WM_KEYUP等。请在代码中使用实际名称。它们以WindowsMessages单位声明。

您是否声明KeyboardHook()使用stdcall调用约定?您显示的代码不是这样做的。这非常重要,因此参数值在调用堆栈上正确传递。

lParam挂钩的WH_KEYBOARD_LL值不是PEventMsg(指向EVENTMSG结构的指针)。该结构用于WH_JOURNALPLAYBACK挂钩。 WH_KEYBOARD_LL使用KBDLLHOOKSTRUCT结构。 Delphi没有声明该特定结构,因此您必须在代码中自行声明它。

请勿忽略回调的Code参数或CallNextHookEx()的返回值。它们很重要。 wParamlParam值仅在Code参数为HC_ACTION(0)时有效。并且CallNextHookEx()的返回值需要在挂钩链上传递。

请改为尝试:

type
  PKBDLLHOOKSTRUCT = ^KBDLLHOOKSTRUCT;
  KBDLLHOOKSTRUCT = record
    vkCode: DWORD;
    scanCode: DWORD;
    flags: DWORD;
    time: DWORD;
    dwExtraInfo: ULONG_PTR;
  end;

function KeyboardHook(Code: Integer; wParam: WPARAM; lParam: LPARAM): LRESULT; stdcall;
begin
  if Code = HC_ACTION then
  begin
    if (wParam = WM_KEYUP) and (App.Inside) then
    begin
      case PKBDLLHOOKSTRUCT(lParam)^.vkCode of
        VK_NEXT: App.Next;
        VK_CAPITAL: App.Show;
      end;
    end;
  end;
  // note that CallNextHookEx() ignores the first parameter,
  // so you could pass 0 instead of ID_Keyboard...
  Result := CallNextHookEx(Hook_ID_Keyboard, Code, wParam, lParam);
end;

function StartHookKeyboard: Boolean; stdcall;
begin
  if Hook_ID_Keyboard = 0 then
    Hook_ID_Keyboard := SetWindowsHookEx(WH_KEYBOARD_LL, @KeyboardHook, HInstance, 0);
  Result := Hook_ID_Keyboard <> 0;
end;

function StopHookKeyboard: Boolean; stdcall;
begin
  if Hook_ID_Keyboard <> 0 then
  begin
    if UnhookWindowsHookEx(Hook_ID_Keyboard) then
      Hook_ID_Keyboard := 0;
  end;
  Result := Hook_ID_Keyboard = 0;
end;

如果代码仍然崩溃,则可能与App有关。什么是App?它在哪里以及如何宣布?它是如何初始化的? Next()Show()实际上做了什么?您正在全局安装挂钩以挂钩所有正在运行的进程,因此App是否以跨进程安全的方式使用?