• Delphi跨进程访问DBGRID


    要想跨进程访问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.
    View Code

    //DLL单元2

    library SnifferLib;
    uses
      Windows,
      Sniffer in 'Sniffer.pas';
    {$R *.res}
    exports
      ExeSniffer;
    begin
    end.
    View Code

    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
    View Code

    http://pan.baidu.com/s/1GFZuZ   下载地址

  • 相关阅读:
    永远不要在MySQL中使用UTF8
    DevExpress 如何向lookUpEditor中添加新值
    DevExpress 如何向lookUpEditor中添加新值
    给DataTable中添加一行数据
    给DataTable中添加一行数据
    【VS】使用vs2017自带的诊断工具(Diagnostic Tools)诊断程序的内存问题
    【VS】使用vs2017自带的诊断工具(Diagnostic Tools)诊断程序的内存问题
    Winform开发的界面处理优化
    Winform开发的界面处理优化
    Linq扩展方法之All 、Any
  • 原文地址:https://www.cnblogs.com/key-ok/p/3358898.html
Copyright © 2020-2023  润新知