ReadProcessMemory продолжает возвращать 0

В настоящее время я разрабатываю небольшой хобби-проект для отображения информации о здоровье в игре на моей клавиатуре 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))

Может кто-нибудь объяснить мне, почему он не работает? Заранее спасибо.


person RodgerB    schedule 06.12.2008    source источник


Ответы (3)


Во-первых, ваша подпись метода неверна, 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, а не дескриптор окна.

person arul    schedule 06.12.2008

Спасибо Аруль, я как бы решил свою проблему.

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.

У кого-нибудь есть идеи относительно того, как я должен приступить к устранению этой проблемы?

person RodgerB    schedule 06.12.2008

сообщение 299: только часть запроса ReadProcessMemory или WriteProcessMemory была выполнена, что означает, что память, которую я пытался прочитать, была защищена.

Спасибо за всю вашу помощь, я собираюсь отметить ответ Арула как ответ.

person RodgerB    schedule 08.12.2008