Попытка чтения или записи защищенной памяти. Это часто указывает на то, что другая память повреждена

Я использую следующий код

Эта ошибка возникает:

Попытка чтения или записи защищенной памяти. Это часто указывает на то, что другая память повреждена. Попытка чтения или записи защищенной памяти. Это часто указывает на то, что другая память повреждена.

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

Пожалуйста, покажи мне правильный путь


person jack rasha    schedule 24.11.2011    source источник


Ответы (2)


Обычно это вызвано неправильным оператором Private Declare Function. Типы, перечисленные в Windows API, отличаются от типов, используемых в коде VB или C#. Это большой список преобразований типов данных между Windows API и .Net: Win32 API C++ в .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

Итак, ваша функция должна выглядеть примерно так. К сожалению, я не знаю, что написать для strData или RetvalData. Я добавил блок 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
person Hand-E-Food    schedule 24.11.2011
comment
Как использовать функцию RegEnumValue? - person jack rasha; 25.11.2011

Вместо этого используйте функциональные возможности встроенного пространства имен 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, я обнаружил, что для обработки результатов нужно проделать немало дополнительной работы:

Как только вы определили, что RegEnumValue был успешным (возвращаемое значение 0), вам необходимо обработать результаты на основе параметра 3 с конца (lpType), который сообщит вам тип данных.

Затем, в зависимости от типа (например, REG_SZ, REG_DWORD и т. д.), вам нужно будет сделать вызов одного из методов API RegQueryValueExA:

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

и т. д., чтобы получить значение в записи реестра.

person competent_tech    schedule 24.11.2011
comment
@jack rasha: обновлен ответ с правильной подписью для RegEnumValueA и дополнительной информацией. - person competent_tech; 25.11.2011
comment
ошибка в: Если RegOpenKey(HKEY_CURRENT_USER, Панель управления\Рабочий стол, hKey) = 0, то 'ошибка - person jack rasha; 25.11.2011
comment
@jackrasha: добавлены обновленные определения для ответа других функций. - person competent_tech; 25.11.2011
comment
@jackrasha: добавлены некоторые дополнительные сведения о работе, которую необходимо выполнить для обработки результатов. - person competent_tech; 25.11.2011