多个ByVal类型声明

时间:2011-10-22 22:03:06

标签: vb.net

我有

Private Declare Function ReadProcessMemory Lib "kernel32" Alias "ReadProcessMemory" (ByVal hProcess As Integer, ByVal lpBaseAddress As Integer, ByRef lpBuffer As Integer, ByVal nSize As Integer, ByRef lpNumberOfBytesWritten As Integer) As Integer

但我也需要

Private Declare Function ReadProcessMemory Lib "kernel32" Alias "ReadProcessMemory" (ByVal hProcess As Integer, ByVal lpBaseAddress As Integer, ByRef lpBuffer As Single, ByVal nSize As Integer, ByRef lpNumberOfBytesWritten As Integer) As Integer

以及其他一些变化。因此,如上例所示,lpBuffer为Single而不是Integer。我怎样才能做到这一点?

更新:好的,现在我正在这样做:

Imports System.Math
Imports System.Threading
Imports System.Runtime.InteropServices

Public Class Form1

'Declare ReadProcessMemory with lpBuffer As IntPtr
Private Declare Function ReadProcessMemory Lib "kernel32" Alias "ReadProcessMemory" (ByVal hProcess As Integer, ByVal lpBaseAddress As Integer, ByRef lpBuffer As IntPtr, ByVal nSize As Integer, ByRef lpNumberOfBytesWritten As Integer) As Integer

'This is the function I am now having trouble with
Public Function memfloat(ByVal address As Long, ByVal processHandle As IntPtr)
        Dim floatvalueinmemory As Single
        ReadProcessMemory(processHandle, address, floatvalueinmemory, 4, 0)
        Dim letstryagain As Single 'floatvalueinmemory didn't give the desired result, so going to try to TryParse
        Single.TryParse(floatvalueinmemory, letstryagain)
        Return CStr(letstryagain) 'returns the same result as floatvalueinmemory did
    End Function

End Class

Partial Public Class NativeMethods
    <DllImport("user32.dll")> _
    Public Shared Function ReadProcessMemory(ByVal hProcess As System.IntPtr, ByVal lpBaseAddress As IntPtr, ByVal lpBuffer As System.IntPtr, ByVal nSize As UInteger, ByVal lpNumberOfBytesRead As IntPtr) As Boolean
    End Function
End Class

memfloat函数用于返回类似“-75,48196”的内容,现在它返回类似“-1,012555E + 09”的内容(实际值不匹配,仅使用这些作为示例),这是为什么我想首先声明多次..如何从IntPtr转换为Single?

的作用是:

Public Function memstring(ByVal address As Long, ByVal length As Int32, ByVal processHandle As IntPtr)
    Dim stringinmemory As Long
    Dim ret1 As Byte() = Nothing
    Dim tStr(length) As Char
    Dim retStr As String = ""
    For i As Int32 = 0 To length - 1
        ReadProcessMemory(processHandle, address + i, stringinmemory, 1, 0)
        ret1 = BitConverter.GetBytes(stringinmemory)
        tStr(i) = System.Text.Encoding.ASCII.GetString(ret1) : retStr += tStr(i)
    Next
    Return retStr
End Function

这正确地将内存值作为字符串返回。所以,是的,现在只是造成问题的单身。

2 个答案:

答案 0 :(得分:2)

无论如何,您正在使用Alias关键字,因此请充分利用它:

Private Declare Function ReadProcessMemoryInt Lib "kernel32" _
    Alias "ReadProcessMemory" (ByVal hProcess As Integer, _
                               ByVal lpBaseAddress As Integer, _
                               ByRef lpBuffer As Integer, _
                               ByVal nSize As Integer, _
                               ByRef lpNumberOfBytesWritten As Integer) As Integer

Private Declare Function ReadProcessMemorySingle Lib "kernel32" _
    Alias "ReadProcessMemory" (ByVal hProcess As Integer, _
                               ByVal lpBaseAddress As Integer, _
                               ByRef lpBuffer As Single, _
                               ByVal nSize As Integer, _
                               ByRef lpNumberOfBytesWritten As Integer) As Integer

您为该函数指定的名称可以是任意的。只有Alias名称必须与库中的名称匹配。在您的代码中,您可以参考ReadProcessMemoryIntReadProcessMemorySingle(或您选择的任何名称)。

(注意:我没有检查您是否正确使用了API,我刚刚回答了有关如何使用不同签名定义相同API函数两次的问题。)

答案 1 :(得分:1)

我启动了P/Invoke Interop Assistant工具(link),找到了ReadProcessMemory并在vb.net中生成了签名:

Partial Public Class NativeMethods    
    '''Return Type: BOOL->int
    '''hProcess: HANDLE->void*
    '''lpBaseAddress: LPCVOID->void*
    '''lpBuffer: LPVOID->void*
    '''nSize: SIZE_T->ULONG_PTR->unsigned int
    '''lpNumberOfBytesRead: SIZE_T*
    <System.Runtime.InteropServices.DllImportAttribute("kernel32.dll", EntryPoint:="ReadProcessMemory")>  _
    Public Shared Function ReadProcessMemory(<System.Runtime.InteropServices.InAttribute()> ByVal hProcess As System.IntPtr, <System.Runtime.InteropServices.InAttribute()> ByVal lpBaseAddress As System.IntPtr, ByVal lpBuffer As System.IntPtr, ByVal nSize As UInteger, ByVal lpNumberOfBytesRead As System.IntPtr) As <System.Runtime.InteropServices.MarshalAsAttribute(System.Runtime.InteropServices.UnmanagedType.Bool)> Boolean
    End Function
End Class

因此,您需要将缓冲区IntPtr转换为各种类型的数组。我建议你研究Marshal类及其静态方法。此处还有指向相关文章SO linkurl 1url 2的链接。可能需要从c#到vb.net的翻译。我还注意到这些在线示例中的函数定义可能会被重载(让我感到惊讶)。