要想跨进程访问DBGRID,貌似只能用HOOK,写一个DLL想办法注入到目标进程。注入成功后,使DLL与目标进程在同一进程空间中(其内有一些细节问题,请参见代码),这时可以访问目标进程的VCL组件。并把VCL组件的数据通过进程通信的方式发给Sniffer进程。
如何进行注入?
可以安装一个WH_CALLWNDPROC钩子,这样当有消息在窗口函数中时,系统就会装载HOOK,即执行DLL部分。
如何发消息?
可以在DLL中设置一个自定义消息,在安装完钩子后,发送一个自定义消息至目标进程的窗口函数。
以下实例可读出另一进程的EDIT、LABEL、DBGRID等控件的值。
如何了解这个原理,跨进程读取StringGrid等控件也并非难事!
//DLL单元1
(*// 标题:窗体嗅探器 作者:王集鹄(Zswang) 博客:http://blog.csdn.net/zswang 日期:2009年3月14日 .//*) unit Sniffer; interface uses Windows,DBGrids,DB; function ExeSniffer( // 执行嗅探 AHandle: THandle; // 窗体句柄 AParam: Integer // 附加参数 ): BOOL; stdcall; implementation // 尊重作者,转贴请注明出处 王集鹄(Zswang) 2009年3月14日 uses SysUtils, Classes, Controls, StdCtrls, Messages; var WM_SNIFFWINDOW: Longword; type TSnifferInfo = packed record rHOOK: HHOOK; rHandle: HWND; rParam: Integer; end; PSnifferInfo = ^TSnifferInfo; var vMapFile: THandle; vSnifferInfo: PSnifferInfo; var ControlAtom: TAtom; ControlAtomString: string = ''; RM_GetObjectInstance: DWORD; // registered window message function FindControl(Handle: HWnd): TWinControl; var OwningProcess: DWORD; begin Result := nil; if (Handle <> 0) and (GetWindowThreadProcessID(Handle, OwningProcess) <> 0) and (OwningProcess = GetCurrentProcessId) then begin if GlobalFindAtom(PChar(ControlAtomString)) = ControlAtom then Result := Pointer(GetProp(Handle, MakeIntAtom(ControlAtom))) else Result := Pointer(SendMessage(Handle, RM_GetObjectInstance, 0, 0)); end; end; { FindControl } function SnifferProc(code: Integer; wparam: WPARAM; lparam: LPARAM): LRESULT; stdcall; var vWinControl: TWinControl; vCopyDataStruct: TCopyDataStruct; I,J: Integer; S: string; tmpGridStr:string; DataSet: TDataSet; begin case code of HC_ACTION: begin if PCWPStruct(lParam)^.message = WM_SNIFFWINDOW then begin if ControlAtomString = '' then begin ControlAtomString := Format('ControlOfs%.8X%.8X', [ GetWindowLong(vSnifferInfo^.rHandle, GWL_HINSTANCE), GetWindowThreadProcessId(vSnifferInfo^.rHandle)]); ControlAtom := GlobalAddAtom(PChar(ControlAtomString)); RM_GetObjectInstance := RegisterWindowMessage(PChar(ControlAtomString)); end; vWinControl := FindControl(vSnifferInfo^.rHandle); if Assigned(vWinControl) then begin for I := 0 to vWinControl.ComponentCount - 1 do begin S := ''; if SameText(vWinControl.Components[I].ClassName, 'TLabel') then begin S := Format('%s: %s', [vWinControl.Components[I].Name, QuotedStr(TLabel(vWinControl.Components[I]).Caption)]); end else if SameText(vWinControl.Components[I].ClassName, 'TMemo') or SameText(vWinControl.Components[I].ClassName, 'TEdit') then begin S := Format('%s: %s', [vWinControl.Components[I].Name, QuotedStr(TLabel(vWinControl.Components[I]).Caption)]); end else if SameText(vWinControl.Components[I].ClassName, 'TDBGrid') then begin DataSet := TDBGrid(vWinControl.Components[I]).DataSource.DataSet; tmpGridStr:=''; for J:=0 to DataSet.RecordCount-1 do begin tmpGridStr:=tmpGridStr+ dataset.Fields[0].AsString+' '+dataset.Fields[1].AsString+' ' ; DataSet.Next; end; S := Format('%s: %s', [vWinControl.Components[I].Name, QuotedStr(tmpGridStr)]); end; vCopyDataStruct.cbData := Length(S); vCopyDataStruct.dwData := 0; vCopyDataStruct.lpData := @S[1]; SendMessage(vSnifferInfo^.rParam, WM_COPYDATA, vSnifferInfo^.rHandle, Integer(@vCopyDataStruct)); end; end; end; end; end; Result := CallNextHookEx(vSnifferInfo^.rHOOK, code, wParam, lParam); end; function ExeSniffer( // 执行嗅探 AHandle: THandle; // 窗体句柄 AParam: Integer // 附加参数 ): BOOL; stdcall; begin vSnifferInfo^.rHandle := AHandle; vSnifferInfo^.rParam := AParam; vSnifferInfo^.rHOOK := SetWindowsHookEx( WH_CALLWNDPROC, SnifferProc, HInstance, GetWindowThreadProcessId(AHandle)); Result := SendMessageTimeout(AHandle, WM_SNIFFWINDOW, 0, 0, SMTO_NORMAL, 3000, THandle(Result)) = 0; UnhookWindowsHookEx(vSnifferInfo^.rHOOK); end; initialization WM_SNIFFWINDOW := RegisterWindowMessage('SnifferLib.SniffWindow'); vMapFile := OpenFileMapping(FILE_MAP_ALL_ACCESS, False, '~Sniffer'); if vMapFile = 0 then vMapFile := CreateFileMapping($FFFFFFFF, nil, PAGE_READWRITE, 0, SizeOf(TSnifferInfo), '~Sniffer'); vSnifferInfo := MapViewOfFile(vMapFile, FILE_MAP_ALL_ACCESS, 0, 0, 0); finalization UnmapViewOfFile(vSnifferInfo); CloseHandle(vMapFile); end.
//DLL单元2
library SnifferLib; uses Windows, Sniffer in 'Sniffer.pas'; {$R *.res} exports ExeSniffer; begin end.
sniffer程序
unit SnifferUnit; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls; type TFormSniffer = class(TForm) ButtonStart: TButton; Memo1: TMemo; EditClassName: TEdit; LabelClassName: TLabel; procedure ButtonStartClick(Sender: TObject); private { Private declarations } procedure WMCOPYDATA(var Msg: TWMCopyData); message WM_COPYDATA; public { Public declarations } end; var FormSniffer: TFormSniffer; implementation {$R *.dfm} function ExeSniffer( // 执行嗅探 AHandle: THandle; // 窗体句柄 AParam: Integer // 附加参数 ): BOOL; stdcall; external 'SnifferLib.dll'; // 执行嗅探 procedure TFormSniffer.ButtonStartClick(Sender: TObject); var vHandle: THandle; begin Memo1.Clear; vHandle := FindWindow(PChar(EditClassName.Text), nil); if vHandle = 0 then Exit; ExeSniffer(vHandle, Handle); end; procedure TFormSniffer.WMCOPYDATA(var Msg: TWMCopyData); var S: string; begin if Msg.CopyDataStruct^.cbData <= 0 then Exit; SetLength(S, Msg.CopyDataStruct^.cbData); Move(Msg.CopyDataStruct^.lpData^, S[1], Msg.CopyDataStruct^.cbData); Memo1.Lines.Add(S); end; end
http://pan.baidu.com/s/1GFZuZ 下载地址