ReadProcessMemory продолжает возвращать 0 - PullRequest
1 голос
/ 07 декабря 2008

В настоящее время я разрабатываю небольшой хобби-проект для отображения информации о здоровье в игре на моей клавиатуре G15 через VB.NET.

Когда я использую ReadProcessMemory через вызов API, он продолжает возвращать ноль. В документации MSDN мне было предложено использовать вызов Marshal.GetLastWin32Error (), чтобы выяснить, что не так, и он возвращает 1400: НЕВЕРНАЯ РУЧКА ОКНА.

Теперь я озадачен тем, хочет ли первый аргумент функции дескриптор окна или идентификатор процесса. Несмотря на это, я пробовал как с FindWindow, так и жестко кодировать идентификатор процесса во время работы приложения (получение из диспетчера задач).

Я пробовал три разные игры: Urban Terror, Grand Theft Auto: SA и 3D пинбол для окон, получая адреса памяти из приложения под названием Cheat Engine; кажется, все они терпят неудачу.

Вот код, который я использую для этого:

API Call:

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))

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

Ответы [ 3 ]

3 голосов
/ 07 декабря 2008

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

1 голос
/ 09 декабря 2008

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

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

1 голос
/ 07 декабря 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 была выполнена.

У кого-нибудь есть идеи, как мне поступить, чтобы решить эту проблему?

...