尝试读取或写入受保护的内存。这通常表明其他内存已损坏

时间:2011-11-24 21:56:11

标签: vb.net registry vb.net-2010

我正在使用以下代码

发生此错误:

尝试读取或写入受保护的内存。这通常表明其他内存已损坏。 尝试读取或写入受保护的内存。这通常表明其他内存已损坏。

Public Class FormRegEnumValue

Private Const ERROR_SUCCESS = 0&
Private Const ERROR_NO_MORE_ITEMS = 259&
Private Const HKEY_CURRENT_USER = &H80000001

Private Const REG_BINARY = 3
Private Const REG_DWORD = 4
Private Const REG_EXPAND_SZ = 2
Private Const REG_SZ = 1

Private Declare Function RegEnumValue Lib "advapi32.dll" Alias "RegEnumValueA" (ByVal hKey As Long, ByVal dwIndex As Long, ByVal lpValueName As String, ByVal lpcbValueName As Long, ByVal lpReserved As Long, ByVal lpType As Long, ByVal lpData As Object, ByVal lpcbData As Long) As Long
Private Declare Function RegCloseKey Lib "advapi32.dll" (ByVal hKey As Long) As Long
Private Declare Function RegOpenKey Lib "advapi32.dll" Alias "RegOpenKeyA" (ByVal hKey As Long, ByVal lpSubKey As String, ByVal phkResult As Long) As Long


Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
    Dim hKey As Long, num As Long, strName As String
    Dim strData As String, Retval As Long, RetvalData As Long

    Const Buffer As Long = 255
    num = 0
    strName = Space(Buffer)
    strData = Space(Buffer)
    Retval = Buffer
    RetvalData = Buffer
    If RegOpenKey(HKEY_CURRENT_USER, "Control Panel\Desktop", hKey) = 0 Then 'error
        While RegEnumValue(hKey, num, strName, Retval, 0, 0&, strData, RetvalData) <> ERROR_NO_MORE_ITEMS
            If RetvalData > 0 Then
                ListBox1.Items.Add(strName + Retval + "  =  " + strData + RetvalData - 1)
            End If
            num = num + 1
            strName = Space(Buffer)
            strData = Space(Buffer)
            Retval = Buffer
            RetvalData = Buffer
        End While
        RegCloseKey(hKey)
    Else
        ListBox1.Items.Add("Error")
    End If
End Sub
End Class

请以正确的方式告诉我

2 个答案:

答案 0 :(得分:5)

这通常是由不正确的Private Declare Function语句引起的。 Windows API中列出的类型与VB或C#代码中使用的类型不同。这是Windows API和.Net之间数据类型转换的绝佳列表:Win32 API C++ to .NET

PInvoke网站通常会列出正确的VB代码。

对于RegEnumValue,修复数据类型,lpcValueName是ByRef,而不是ByVal:

Declare Auto Function RegEnumValue Lib "Advapi32" ( _
    ByVal hKey As IntPtr, _
    ByVal dwIndex As Integer, _
    ByVal lpValueName As StringBuilder, _
    ByRef lpcValueName As Integer, _
    ByVal lpReserved As IntPtr, _
    ByVal lpType As IntPtr, _
    ByVal lpData As IntPtr, _
    ByVal lpcbData As IntPtr _
) As Integer

对于RegCloseKey,只需修复数据类型:

Declare Function RegCloseKey Lib "advapi32.dll" ( _
    ByVal hKey As UIntPtr _
) As Integer

对于RegOpenKey,修复数据类型并将phkResult更改为ByRef:

Private Declare Function RegOpenKey Lib "advapi32.dll" Alias "RegOpenKeyA" ( _
    ByVal hKey As Integer, _
    ByVal lpSubKey As String, _
    ByRef phkResult As IntPtr _
) As Integer

所以你的功能应该更像这样。不幸的是,我不确定要为strDataRetvalData写些什么。我添加了Try/Finally块,即使发生错误也会确保调用RegCloseKey。你想确保你总是关闭事物,特别是如果出现问题。

Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
    Const Buffer As Long = 255
    Dim hKey As IntPtr = IntPtr.Zero
    Dim num As Integer = 0
    Dim strName As New StringBuilder
    Dim strData As IntPtr = ' I'm not surte what goes here.
    Dim Retval As Integer = Buffer
    Dim RetvalData As IntPtr = ' I'm not surte what goes here.
    If RegOpenKey(HKEY_CURRENT_USER, "Control Panel\Desktop", hKey) = 0 Then 'error
        Try
            While RegEnumValue(hKey, num, strName, Retval, IntPtr.Zero, IntPtr.Zero, strData, RetvalData) <> ERROR_NO_MORE_ITEMS
                If RetvalData > 0 Then
                    ListBox1.Items.Add(strName.ToString + Retval + "  =  " + strData + RetvalData - 1)
                End If
                num = num + 1
                strName = New StringBuilder(Buffer)
                strData = ' I'm not sure what goes here.
                Retval = Buffer
                RetvalData = ' I'm not surte what goes here.
            End While
        Finally
            RegCloseKey(hKey)
        End Try
    Else
        ListBox1.Items.Add("Error")
    End If
End Sub

答案 1 :(得分:1)

使用内置Microsoft.Win32.Registry命名空间中包含的功能。

您可以在MSDN中找到参考资料和大量示例。

<强>更新

如果您需要使用API​​,则必须将RegEnumValue上的签名更改为:

Declare Function RegEnumValue Lib "advapi32.dll"  Alias "RegEnumValueA"(ByVal hKey As Integer, ByVal dwIndex As Integer, ByVal lpValueName As String, ByRef lpcbValueName As Integer, ByVal lpReserved As Integer, ByRef lpType As Integer, ByRef lpData As StringBuilder, ByRef lpcbData As Integer) As Integer

然后,将strData的类型更改为StringBuilder,并创建一个StringBuilder的新实例,当前正在使用空格填充strData:

strData = New StringBuilder(buffer)

也可能需要进行其他更改,但这是目前最重要的更改。

更新2

另一个声明需要将其Long值更改为Integer,RegOpenKey的结果参数为ByRef:

Private Declare Function RegCloseKey Lib "advapi32.dll" (ByVal hKey As Integer) As Integer
Private Declare Function RegOpenKey Lib "advapi32.dll" Alias "RegOpenKeyA" (ByVal hKey As Integer, ByVal lpSubKey As String, ByRef phkResult As Integer) As Integer

更新3

在查看旧的API代码后,我发现您需要做一些额外的工作才能处理结果:

一旦确定Re​​gEnumValue成功(返回值为0),您需要根据末尾的3参数(lpType)处理结果,这将告诉您数据的类型。

然后,根据类型(即REG_SZ,REG_DWORD等),您需要调用其中一个RegQueryValueExA API方法:

Declare Function RegQueryValueExString Lib "advapi32.dll"  Alias "RegQueryValueExA"(ByVal hKey As Integer, ByVal lpValueName As String, ByVal lpReserved As Integer, ByRef lpType As Integer, ByVal lpData As String, ByRef lpcbData As Integer) As Integer

Declare Function RegQueryValueExLong Lib "advapi32.dll"  Alias "RegQueryValueExA"(ByVal hKey As Integer, ByVal lpValueName As String, ByVal lpReserved As Integer, ByRef lpType As Integer, ByRef lpData As Integer, ByRef lpcbData As Integer) As Integer

等。为了检索注册表项中的值。