В настоящее время я разрабатываю небольшой хобби-проект по отображению информации о здоровье в игре на моей клавиатуре G15 через VB.NET.
Когда я использую ReadProcessMemory через вызов API, он продолжает возвращать ноль. Документация MSDN рекомендовала мне использовать вызов Marshal.GetLastWin32Error (), чтобы выяснить, что не так, и он возвращает 1400: INVALID WINDOW HANDLE.
Теперь я не понимаю, нужен ли первый аргумент функции дескриптор окна или идентификатор процесса. Тем не менее, я пробовал как с FindWindow, так и с жестким кодированием идентификатора процесса во время работы приложения (получая его из диспетчера задач).
Я пробовал три разные игры: Urban Terror, Grand Theft Auto: SA и 3D pinball для Windows, получая адреса памяти из приложения под названием Cheat Engine; они все, кажется, терпят неудачу.
Вот код, который я использую для этого:
Вызов API:
Private Declare Function ReadProcessMemory Lib "kernel32" ( _
ByVal hProcess As Integer, _
ByVal lpBaseAddress As Integer, _
ByRef lpBuffer As Single, _
ByVal nSize As Integer, _
ByRef lpNumberOfBytesWritten As Integer _
) As Integer
Метод:
Dim address As Integer
address = &HA90C62&
Dim valueinmemory As Integer
Dim proc As Process = Process.GetCurrentProcess
For Each proc In Process.GetProcesses
If proc.MainWindowTitle = "3D Pinball for Windows - Space Cadet" Then
If ReadProcessMemory(proc.Handle.ToInt32, address, valueinmemory, 4, 0) = 0 Then
MsgBox("aww")
Else
MsgBox(CStr(valueinmemory))
End If
End If
Next
Dim lastError As Integer
lastError = Marshal.GetLastWin32Error()
MessageBox.Show(CStr(lastError))
Может кто-нибудь объяснить мне, почему он не работает? Заранее спасибо.





Во-первых, подпись вашего метода неверна: Single = Float, а исходный параметр имеет тип LPBUF.
Используйте эту подпись метода:
<DllImport("kernel32.dll", SetLastError=true)> _
Public Shared Function ReadProcessMemory( _
ByVal hProcess As IntPtr, _
ByVal lpBaseAddress As IntPtr, _
<Out()>ByVal lpBuffer() As Byte, _
ByVal dwSize as Integer, _
ByRef lpNumberOfBytesRead as Integer
) As Boolean
End Function
Во-вторых, я считаю, что дескриптор hProcess ожидает дескриптор, открытый функцией OpenProcess, а не дескриптор окна.
Спасибо, арул, я вроде как решил свою проблему.
Dim address As Integer
address = &HA90C62&
Dim floatvalueinmemory() As Byte
Dim proc As Process = Process.GetCurrentProcess
For Each proc In Process.GetProcesses
If proc.MainWindowTitle = "3D Pinball for Windows - Space Cadet" Then
Dim winhandle As IntPtr = OpenProcess(PROCESS_ACCESS.PROCESS_VM_READ, True, proc.Id)
If ReadProcessMemory(winhandle, address, floatvalueinmemory, 4, 0) = 0 Then
Dim lastError As Integer
lastError = Marshal.GetLastWin32Error()
MessageBox.Show(CStr(lastError))
MsgBox("aww")
Else
MsgBox("woo")
End If
CloseHandle(winhandle)
End If
Next
Теперь он считает, что дескриптор действителен, и пытается прочитать память процессов, но я получаю сообщение об ошибке 299: Выполнена только часть запроса ReadProcessMemory или WriteProcessMemory.
Есть ли у кого-нибудь идеи, как мне решить эту проблему?
сообщение 299: Выполнена только часть запроса ReadProcessMemory или WriteProcessMemory, значит, память, которую я пытался прочитать, была защищена.
Спасибо за вашу помощь, я отмечу ответ Арула как ответ.