使用SetWindowsHookEx一直发生错误,提示如下:
Access violation at address 00D433DB. Write of address CC00D41B下面是我的代码:
--------------------------
EXE部分:
unit UnitMain;interfaceuses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls;type
  TfrmMain = class(TForm)
    Button1: TButton;
    Button2: TButton;
    procedure FormCreate(Sender: TObject);
    procedure Button1Click(Sender: TObject);
    procedure Button2Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;var
  frmMain: TfrmMain;implementation
     procedure StartHook(QQHandle : longint); external 'Inject.dll' name 'StartHook';
     procedure StopHook; external 'Inject.dll' name 'StopHook';
{$R *.dfm}procedure TfrmMain.FormCreate(Sender: TObject);
begin
     Self.Icon := Application.Icon;
     Application.Title := Self.Caption;
end;procedure TfrmMain.Button1Click(Sender: TObject);
begin
     StartHook(GetWindowThreadProcessID(Self.Handle,nil));
end;procedure TfrmMain.Button2Click(Sender: TObject);
begin
     StopHook;
end;end.-------------------------
DLL部分:
library Inject;{ Important note about DLL memory management: ShareMem must be the
  first unit in your library's USES clause AND your project's (select
  Project-View Source) USES clause if your DLL exports any procedures or
  functions that pass strings as parameters or function results. This
  applies to all strings passed to and from your DLL--even those that
  are nested in records and classes. ShareMem is the interface unit to
  the BORLNDMM.DLL shared memory manager, which must be deployed along
  with your DLL. To avoid using BORLNDMM.DLL, pass string information
  using PChar or ShortString parameters. }uses
  SysUtils,
  Classes,
  UnitHook in 'UnitHook.pas';{$R *.res}
exports
    StartHook,StopHook;begin
end.----------------
unit UnitHook;interfaceuses Windows, SysUtils, Classes, math, messages, dialogs;     procedure StartHook(QQProcID : Cardinal);stdcall;
     procedure StopHook;stdcall;implementationvar
   MessageHook : HHOOK;
function MyHookProc(iCode:Integer;wParam:WPARAM;lParam:LPARAM):LRESULT; stdcall;
begin
     if wParam = WM_MOUSEMOVE then
        showmessage('Get It');
     Result := CallNextHookEx(MessageHook, iCode, wParam, lParam);
end;procedure StartHook(QQProcID : Cardinal);stdcall;export;
begin
     if MessageHook = 0 then
     begin
          MessageHook := SetWindowsHookEx(WH_GETMESSAGE,MyHookProc,HInstance,QQProcID);
          if longint(MessageHook) = 0 then
             showmessage(SysErrorMessage(GetLastError));
     end;
end;procedure StopHook;stdcall;export;
begin
     if MessageHook <> 0 then
     begin
          UnHookWindowsHookEx(MessageHook);
          MessageHook := 0;
     end;
end;end.

解决方案 »

  1.   

    问题在于执行StartHook过程的时候,SetWindowsHookEx返回总是0。
    但showmessage(SysErrorMessage(GetLastError));显示“操作成功完成”。
    请各位指点一下究竟错在哪里了?
      

  2.   

    改成这样试试
    SetWindowsHookEx(WH_GETMESSAGE,MyHookProc,GetCurrentThreadId(),QQProcID);好像曾看资料里说过,除了WH_JOURNALRECORD和WH_JOURNALPLAYBACK这两个钩子(或者还有其他的)可以用全局实例以外,其他的都只能用局部,所以应该不能用HInstance
      

  3.   

    已经改成 SetWindowsHookEx(WH_GETMESSAGE,MyHookProc,GetCurrentThreadId(),QQProcID); 了。
    但还是出现“Access violation at address 00D433DB. Write of address CC00D41B”。
    我只想钩一个进程,不想钩全局的,难道SetWindowsHookEx的第4个参数一定要是0吗?
      

  4.   

    把第三个参数设成0,其实你的第四个参数已经是要钩的进程了,GetCurrentThreadId()就是获得当前进程的,我刚开始看错了
      

  5.   

    SetWindowsHookEx(WH_GETMESSAGE,MyHookProc,GetCurrentThreadId(),QQProcID); 了。第三个参数 跟 第四个参数交换
      

  6.   

    HHOOK SetWindowsHookEx(
      int idHook,        // type of hook to install
      HOOKPROC lpfn,     // address of hook procedure
      HINSTANCE hMod,    // handle to application instance
      DWORD dwThreadId   // identity of thread to install hook for
    );
    看仔细里面参数的意义哦SetWindowsHookEx(WH_MOUSE, @HookMouseProc, hModule, iThreadID);
      

  7.   

    发现问题所在了,参数传给DLL中的StartHook之后,值就变了,请问,这是怎么回事?
      

  8.   

    To 蓝色忧郁:
    把stdcall去掉吗?还是改成别的什么?