WindowsDevCenter.com
oreilly.comSafari Books Online.Conferences.

advertisement


AddThis Social Bookmark Button

Reading and Writing Registry Keys with Visual Basic
Pages: 1, 2, 3

Getting Information about Keys

Once you've opened a key, you sometimes know what subkeys and values it contains. In other cases, you may not be completely sure about its keys and values. And sometimes, you have absolutely no idea what its subkeys and their values are. To help you handle situations in which you don't know the number and names of subkeys, you can call the RegQueryInfoKey function. Its syntax is:



Public Declare Function RegQueryInfoKey Lib "advapi32.dll" Alias "RegQueryInfoKeyA" _
       (ByVal hKey As Long, _               ' Handle of key to query
        ByVal lpClass As String, _          ' Class (unsued except for remote keys)
        lpcbClass As Long, _                ' Length of class string (unused)
        ByVal lpReserved As Long, _         ' Reserved, must be 0
        lpcSubKeys As Long, _               ' Number of subkeys
        lpcbMaxSubKeyLen As Long, _         ' Length of longest subkey name
        lpcbMaxClassLen As Long, _          ' Length of longest class name (unused)
        lpcValues As Long, _                ' Number of values
        lpcbMaxValueNameLen As Long, _      ' Length of longest value name
        lpcbMaxValueLen As Long, _          ' Length of longest value 
        lpcbSecurityDescriptor As Long, _   ' Security Descriptor
        lpftLastWriteTime As FILETIME _     ' Date/time of last write to key
       ) As Long

Note that most of these arguments are passed to the function by reference; that is, on return, their values are updated to reflect the results of the query. RegQueryInfoKey provides us with the following items of information:

  • The number of subkeys. With this information, we can enumerate subkeys using the RegEnumKey function.

  • The greatest number of characters in a subkey name. With this information, we can allocate a large enough buffer when calling RegEnumKey to retrieve the complete name of each subkey. Each of these subkeys can then be opened using the RegOpenKeyEx function.

  • The number of values. With this information, we can enumerate values using the RegEnumValue function.

  • The greatest number of characters in a named value. With this information, we can allocate a sufficiently large buffer when calling RegEnumValue to retrieve the complete name of each value.

  • The greatest number of bytes in a value. With this information, we can allocate a large enough buffer when calling RegQueryValueEx to retrieve all the data belonging to each value.

Once you know the number of subkeys belonging to an open key, you can iterate them using the RegEnumKeyEx function. Its syntax is:

Public Declare Function RegEnumKeyEx Lib "advapi32.dll" Alias "RegEnumKeyExA" _
      (ByVal hKey As Long, _           ' Handle of open key       	
       ByVal dwIndex As Long, _        ' Index of subkey	
       ByVal lpName As String, _       ' Name of key
       lpcbName As Long, _             ' Length of name buffer
       ByVal lpReserved As Long, _     ' Reserved, must be 0	
       ByVal lpClass As String, _      ' Class name (usually usused)
       lpcbClass As Long, _            ' Length of class name
       lpftLastWriteTime As FILETIME _ ' Date of last write
      ) As Long

The following code illustrates the use of RegQueryInfoKey, RegEnumKeyEx, and RegOpenKeyEx to open each of the subkeys of HKEY_CURRENT_USER\Control Panel:

Dim lResult As Long
Dim hKey As Long
Dim lNumKeys As Long             ' Number of subkeys of open key
Dim lSubkeyNameLen As Long       ' Length of the longest subkey name
Dim ft As FILETIME

Dim sRegPath As String

Dim sa As SECURITY_ATTRIBUTES    ' Use default security attributes of process
sa.nLength = Len(sa)
sa.bInheritHandle = CLng(True)

If RegOpenKeyEx(HKEY_CURRENT_USER, "Control Panel", 0, KEY_READ, hKey) = ERROR_SUCCESS Then
   ' Get subkey information
   lResult = RegQueryInfoKey(hKey, vbNullString, 0, 0, lNumKeys, lSubkeyNameLen, _
             0, 0, 0, 0, 0, ft)
   If lResult = ERROR_SUCCESS Then
      Dim sMsg As String
      sMsg = "Key: HKEY_CURRENT_USER\Control Panel" & vbCrLf & vbCrLf
      sMsg = sMsg & "Subkeys: " & lNumKeys & vbCrLf
      sMsg = sMsg & "Longest subkey name: " & lSubkeyNameLen & vbCrLf
      MsgBox sMsg
   End If
   ' Use subkey information to enumerate subkeys
   Dim lCtr As Long
   Dim sBuffer As String
   Dim lBuffer As Long
   Dim hSubkey As Long
   ' Loop as many times as there are subkeys
   For lCtr = 0 To lNumKeys - 1
      ' Initialize buffer to hold name to be 1 greater than maximum length
      sBuffer = Space(lSubkeyNameLen) & Chr(0)
      lBuffer = Len(sBuffer)
      RegEnumKeyEx hKey, lCtr, sBuffer, lBuffer, 0, vbNullString, 0, ft
      ' Trim returned buffer to extract key name
      sBuffer = Left(sBuffer, lBuffer)
      
      sMsg = "Key " & lCtr & ": " & sBuffer & vbCrLf
      
      ' Open subkey
      RegOpenKeyEx hKey, sBuffer, 0, KEY_READ, hSubkey
      sMsg = sMsg & "   Returned handle " & Hex(hSubkey) & vbCrLf
      MsgBox sMsg
      
      RegCloseKey hSubkey
   Next
   RegCloseKey hKey
Else
   MsgBox "Unable to open key: " & lResult
End If

Note that the code calls RegQueryInfoKey to determine the total number of subkeys and the number of characters in the longest subkey name. Since we're not interested in any of the other information that the function is able to retrieve, we simply provide default literal values (0 for Longs, the vbNullString constant for Strings) in place of the arguments we don't care about.

The loop that repeatedly calls RegEnumKeyEx has a starting index value of 0 and a maximum value of 1 less than the total number of subkeys. Failing to begin the loop at 0 will cause an error. For each call to RegEnumKeyEx, we initialize a buffer whose length is one greater than the maximum number of characters in a subkey name; this allows for the full subkey name to be written to the buffer, along with a terminating null character (or Chr(0)). When RegEnumKeyEx returns, lBuffer is updated to reflect the actual number of characters in the subkey name without the terminating null character. The call to the intrinsic VB Left function discards any portion of the string that is unnecessary. Once we have extracted the name of the subkey, we can call RegOpenKeyEx to open that key.

Deleting a Registry Key

Deleting a registry key would appear to be a straightforward matter: you just call the RegDeleteKey function, whose syntax is:

Public Declare Function RegDeleteKey Lib "advapi32.dll" Alias "RegDeleteKeyA" _
       (ByVal hKey As Long, _                 ' Handle of open key
        ByVal lpSubKey As String _            ' Path from handle to key
       ) As Long

Here, hKey is a handle to an open key, and lpSubKey is a string containing the path to the subkey to be deleted. Since the second parameter cannot be a null string, the function requires that you delete a subkey of an open key. The complication, however, is that on Windows NT/2000/XP systems, the function fails if the subkey to be deleted itself contains any subkeys.

You can work around this problem in either of two ways:

  • You can write code that uses recursion to iterate each of the child keys belonging to the key that you'd like to delete.
  • You can call the Windows Shell library's SHDeleteKey function, which iterates and deletes the child keys before deleting the key itself.

Since relying on operating system services rather than writing code that duplicates system services is sound practice, calling SHDeleteKey is far preferable to writing your own code. The syntax of SHDeleteKey is:

Public Declare Function SHDeleteKey Lib "shlwapi.dll" Alias "SHDeleteKeyA" _
       (ByVal hKey As Long, ByVal pszSubKey As String) As Long

You could then delete the HKEY_CURRENT_USER\Software\MyCompany\MyCorporateApp key and its child keys with the following code:

Dim lResult As Long
Dim hKey As Long
If RegOpenKeyEx(HKEY_CURRENT_USER, "Software", 0, KEY_ALL_ACCESS, hKey) = ERROR_SUCCESS Then
   lResult = SHDeleteKey(hKey, "MyCompany")
   RegCloseKey hKey
End If

Ron Petrusha is the author and coauthor of many books, including "VBScript in a Nutshell."


Return to WindowsDevCenter.com.