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
The greatest number of characters in a subkey name. With this information, we can allocate a large enough buffer when calling
RegEnumKeyto retrieve the complete name of each subkey. Each of these subkeys can then be opened using the
The number of values. With this information, we can enumerate values using the
The greatest number of characters in a named value. With this information, we can allocate a sufficiently large buffer when calling
RegEnumValueto 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
RegQueryValueExto 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
RegOpenKeyEx to open each of the subkeys of
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 (
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
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
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
SHDeleteKeyfunction, 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
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.
Getting Information of Specific Register
2006-12-09 02:00:36 shivkant [View]
2004-11-23 09:20:00 tekhead009 [View]
2004-12-02 12:51:41 LukeM [View]