我是编程新手。我使用的是 Delphi 10.4 Community Edition。我正在尝试运行BassPlayer演示项目,但在编译和运行时遇到错误。错误发生在名为wa_ipc.pas
的文件的第1691行。我不知道如何修复此错误。
function SendMessageRetStr(wnd: HWND; uMsg: UINT; wParam: WPARAM; lParam: LPARAM): String;
var
dwProcessId: DWORD;
phandle: THandle;
P: Pointer;
C: Cardinal;
PB: Pointer;
B: Byte;
begin
Result := '';
GetWindowThreadProcessID(wnd, pointer(dwProcessId));
phandle := OpenProcess(PROCESS_VM_READ, False, dwProcessId);
if phandle = 0 then exit;
P := Pointer(SendMessage(wnd, uMsg, wParam, lParam));
PB := nil;
B := 0;
repeat
if not ReadProcessMemory(phandle,P,@PB,1,C) then break; (*<-- Error message here*)
B := Byte(PB);
if B <> 0 then begin
Result := Result + Chr(B);
end;
P := Pointer(DWord(P)+1);
until (B=0);
CloseHandle(phandle);
end;
我得到的错误是:
[dcc32错误] wa_ipc.pas(1691):E2033实参和形参的类型必须相同
在Winapi.Windows.pas
单元中,ReadProcessMemory()
函数声明为:
function ReadProcessMemory(hProcess: THandle; const lpBaseAddress: Pointer; lpBuffer: Pointer; nSize: SIZE_T; var lpNumberOfBytesRead: SIZE_T): BOOL; stdcall;
1条答案
按热度按时间hyrbngr71#
我发现这段代码有很多问题。
GetWindowThreadProcessId()
的第二个参数中使用pointer(dwProcessId)
是错误的。它在运行时 * 不会 * 按预期工作。您正在传递一个无效的内存地址供API写入,导致 * 未定义的行为 *。您需要改用@dwProcessId
。ReadProcessMemory()
的第三个参数中使用@PB
是错误的。您正在从远程进程阅读1个字节到Pointer
变量中,然后您正在将该Pointer
截断为Byte
。虽然这在运行时 * 将 * 表现为预期的行为,但在 * 逻辑上 * 是错误的,您确实应该使用@B
并完全删除PB
。ReadProcessMemory()
的第5个参数中使用C
错误。这是导致编译器错误的原因。在Win32 API中,该参数需要指向SIZE_T
的 * 指针 *(它是指针大小的无符号整数),不是Cardinal
的 * 值 *(它是一个固定大小的32位无符号整数)。在 Delphi 的Winapi.Windows
单元中,该参数被声明为对SIZE_T
变量的var
引用,而不是Cardinal
变量的var
引用,因此会出现编译器错误。您必须将变量声明为与var
引用所需的完全相同的数据类型。UnicodeString
中。除非所讨论的字符是纯ASCII字符,否则结果将不是您所期望的。Dword
是一个32位整数,因此只有当您的应用被编译为32位可执行文件时,这种转换才能正常工作,因为32位可执行文件在运行时使用32位内存地址。但在64位可执行文件中,您可能会截断指针指向的内存地址。您需要使用DWORD_PTR
(或等效的)来代替。现在,说了这么多,试着做一些类似这样的事情: