Reputation: 85
I am using the following code
This error occurs :
Attempted to read or write protected memory. This is often an indication that other memory is corrupt. Attempted to read or write protected memory. This is often an indication that other memory is corrupt.
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
Please show me the right way
Upvotes: 3
Views: 18511
Reputation: 44931
Use the functionality contained in the built-in Microsoft.Win32.Registry namespace instead.
You can find the reference and plenty of examples in MSDN.
Update
If you need to use the API, then the signature on RegEnumValue has to be changed to something like:
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
Then, change the type of strData to StringBuilder and create a new instance of StringBuilder where you are currently filling strData with spaces:
strData = New StringBuilder(buffer)
There may need to be other changes made as well, but that is the big one for now.
Update 2
The other declaration need to have their Long values changed to Integer and the result parameter for RegOpenKey is 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
Update 3
After reviewing my old API code, I discovered that you need to do quite a bit of additional work in order to process the results:
Once you have determined that RegEnumValue was successful (return value of 0), you need to process the results based on the 3 parameter from the end (lpType), which will tell you the type of data.
Then, based on the type (i.e. REG_SZ, REG_DWORD, etc), you will need to make a call to one of the RegQueryValueExA API methods:
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
etc. in order to retrieve the value in the registry entry.
Upvotes: 1
Reputation: 12794
This is usually caused by an incorrect Private Declare Function
statement. The types listed in the Windows API are different to those used in VB or C# code. This is a great list of data type conversions between the Windows API and .Net: Win32 API C++ to .NET
The PInvoke site often has the correct VB code listed.
For RegEnumValue, fix the data types, and lpcValueName
is a ByRef, not a 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
For RegCloseKey, just fix the data types:
Declare Function RegCloseKey Lib "advapi32.dll" ( _
ByVal hKey As UIntPtr _
) As Integer
For RegOpenKey, fix the data types and change phkResult to a ByRef:
Private Declare Function RegOpenKey Lib "advapi32.dll" Alias "RegOpenKeyA" ( _
ByVal hKey As Integer, _
ByVal lpSubKey As String, _
ByRef phkResult As IntPtr _
) As Integer
So your function should look more like this. Unfortunately, I'm not sure what to write for strData
or RetvalData
. I added in a Try/Finally
block which will make sure RegCloseKey
is called even if an error occurs. You want to make sure you always close things, especially if something goes wrong.
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
Upvotes: 5