ReadProcessMemory продолжает возвращать 0
-
19-08-2019 - |
Вопрос
В настоящее время я разрабатываю небольшой хобби-проект для отображения информации о состоянии здоровья в игре на моей клавиатуре G15 через VB.NET.
Когда я использую ReadProcessMemory через вызов API, он продолжает возвращать ноль.Документация MSDN рекомендовала мне использовать Marshal.Вызов GetLastWin32Error(), чтобы выяснить, что не так, возвращает 1400:НЕДОПУСТИМЫЙ ДЕСКРИПТОР ОКНА.
Теперь я запутался в том, нужен ли первому аргументу функции дескриптор окна или идентификатор процесса.Несмотря на это, я пробовал как с помощью 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.
Используйте этот метод signature:
<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 означало, что память, которую я пытался прочитать, была защищена.
Спасибо за всю вашу помощь, я собираюсь отметить ответ арула как ответ.