各位大哥大姐,我想读取某进程的内存内容,用到ReadProcessMemory,但是读取失败,它没出错,但总返回False.各位帮帮我看是什么原因,谢谢!全部代码如下:unit Unit1;interfaceuses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, TLHelp32;type
  TForm1 = class(TForm)
    Button1: TButton;
    Memo1: TMemo;
    Label1: TLabel;
    Label2: TLabel;
    Label3: TLabel;
    Label4: TLabel;
    procedure Button1Click(Sender: TObject);
  private
    procedure GetProID(StrList: TStringList);
    procedure GetNum(ProID: Cardinal);
    { Private declarations }
  public
    { Public declarations }
  end;var
  Form1: TForm1;implementation{$R *.dfm}procedure TForm1.Button1Click(Sender: TObject);
var
  TempStr: TStringList;
  i: integer;
begin
  TempStr := TStringList.Create;
  GetProID(TempStr);
  Memo1.Lines := TempStr;
  for i := 0 to TempStr.Count - 1 do
    GetNum(StrToInt(TempStr.Strings[i]));
  TempStr.Free;
end;procedure TForm1.GetNum(ProID: Cardinal);   //在进程地址空间中读取内存
var
  _SystemInfo: _SYSTEM_INFO;
  minP, maxP, TempPointer: Pointer;
  sPageSize: Cardinal;
  ProHandle: THandle;
  sMemoryInfo: MEMORY_BASIC_INFORMATION;  // MEMORY_BASIC_INFORMATION结构,用于返回内存空间的信息
  pBuffe: Pointer;
  rReadSize: Cardinal;
  TempStr: String;
  TempArry: array of Char;
begin
  ProHandle := OpenProcess(PROCESS_ALL_ACCESS, False, ProID);  //得到进程句柄
  GetSystemInfo(_SystemInfo);  //得到0~~2GB其中的一部分的起点和终点
  minP := _SystemInfo.lpMinimumApplicationAddress;
  maxP := _SystemInfo.lpMaximumApplicationAddress;
  sPageSize := _SystemInfo.dwPageSize;
  TempPointer := minP;
  Label2.Caption := IntToStr(integer(maxP));
  
  while integer(TempPointer) < integer(maxP) do
  begin
    VirtualQueryEx(ProHandle,           // 进程的句柄
                   TempPointer,         // 内存地址指针
                   sMemoryInfo,         // 指向MEMORY_BASIC_INFORMATION结构的指针,用于返回内存空间的信息
                   SizeOf(MEMORY_BASIC_INFORMATION)
                   );
    if (sMemoryInfo.Type_9 = MEM_PRIVATE)                   //私有页面
       and (sMemoryInfo.AllocationProtect = PAGE_READWRITE) //可读写页面
       and (sMemoryInfo.State = MEM_RESERVE)                //已提交页面
      then
    begin
      pBuffe := Nil;
      if ReadProcessMemory(ProHandle,                    // 被读取进程的句柄
                           sMemoryInfo.BaseAddress,      // 读的起始地址
                           pBuffe,                       //将这段内存读到自己的缓冲里面
                           SizeOf(Integer),                    //一次读取的字节数
                           rReadSize                     //实际读取的字节数
                           ) then
      begin
        SetLength(TempArry, sPageSize);
        FillChar(TempArry, Length(TempArry), #0);
        CopyMemory(@TempArry[0], pBuffe, sPageSize);
        StrPCopy(@TempArry, TempStr);
        
        Application.ProcessMessages;
        if Trim(TempStr) <> '' then
          Memo1.Lines.Add(TempStr);
      end;
    end;    Application.ProcessMessages;
    Label4.Caption := IntToStr(integer(TempPointer));
    Inc(Integer(TempPointer), sPageSize);             //指针向前偏移一个内存块
  end;end;procedure TForm1.GetProID(StrList: TStringList);   //取得指定应用程序的进程ID
var
  sProcessEntry32: TProcessEntry32;
  sHandle: THandle;
  sBool: Boolean;
begin
  if not assigned(StrList) then
    Exit;
  sHandle := CreateToolhelp32Snapshot(TH32CS_SNAPALL, 0);
  sBool := Process32First(sHandle, sProcessEntry32);
  while sBool do
  begin //遍历进程
    if UpperCase(sProcessEntry32.szExeFile) = UpperCase('abc.exe') then   //查找进程名为abc.exe的应用程序
      StrList.Add(Trim(IntToStr(sProcessEntry32.th32ProcessID)));         //将其PID添加到列表中.
    sBool := Process32Next(sHandle, sProcessEntry32);
  end;
  CloseHandle(sHandle);
end;end.

解决方案 »

  1.   

    pBuffe   :=   Nil; 
    if   ReadProcessMemory(ProHandle,                     //   被读取进程的句柄 
         sMemoryInfo.BaseAddress,             //   读的起始地址 
         pBuffe,                                  //将这段内存读到自己的缓冲里面 
         SizeOf(Integer),                                         //一次读取的字节数 
         rReadSize                                           //实际读取的字节数 
         )   then 这里不能另pBuffe   :=   Nil; 应该给pBuffer分配内存。如pBuffe := GetMemory(ReadSize);
      

  2.   

    我也是菜鸟,改了你的程序,我这里试了试可以用
    procedure TForm1.Button1Click(Sender: TObject);
    var
      sProcessEntry32: TProcessEntry32;
      sHandle,ProcessHandle: THandle;
      sBool: Boolean;
      test:integer;
      lpNumberOfBytes:DWORD;
    begin
      sHandle := CreateToolhelp32Snapshot(TH32CS_SNAPALL, 0);
      sBool := Process32First(sHandle,sProcessEntry32);
      while sBool do
      begin
        if UpperCase(sProcessEntry32.szExeFile)<> UpperCase('abc.exe') then
        begin
          sBool := Process32Next(sHandle, sProcessEntry32);
        end
        else
        begin
          sbool:=false;
          ProcessHandle:=OpenProcess(PROCESS_ALL_ACCESS,False,sProcessEntry32.th32ProcessID );
          if ProcessHandle<>0 then
          begin
            ReadProcessMemory(ProcessHandle,Pointer(地址),@test,sizeof(test),lpNumberOfBytes);
            edit1.Text:=inttostr(test);
          end;
          closehandle(processhandle);
        end;
      end; 
      CloseHandle(sHandle);
    end;
      

  3.   

    现在每个进程的物理内存地址都是独立的,不可以直接访问其它进程的内存地址,不过winapi当中有函数提供了访问了其它进程的内存地址。
    网上有例子的
      

  4.   

    要读到pBuffe时,就得先GETMEM,然后才能使用   if ReadProcessMemory(ProHandle,                    // 被读取进程的句柄 
                               sMemoryInfo.BaseAddress,      // 读的起始地址 
                               pBuffe,                       //将这段内存读到自己的缓冲里面 
                               SizeOf(Integer),                    //一次读取的字节数 
                               rReadSize                     //实际读取的字节数 
                               ) then