Opening a Registry Key
Opening the key is always the first step involved in working with a registry key (unless you intend to work with one of the top-level keys, which are always considered open). Once you open the key, you work with its handle, or
hKey. We can take advantage of the fact that a successful open operation results in a valid handle to a registry key when determining whether a particular key exists, which is one of the more common operations performed on registry keys. For example, consider the following example function:
Private Function RegKeyExists(hKey As Long, sKeyPath As String) As Boolean Dim lResult As Long Dim hSubkey As Long lResult = RegOpenKeyEx(hKey, sKeyPath, 0, KEY_EXECUTE, hSubkey) ' Determine if handle is valid If hSubkey <> 0 Then RegKeyExists = True RegCloseKey hKey End If End Function
This example function takes two parameters: a handle to a registry key (or a top-level registry key), and the path from the open key to the registry key to be opened. It then calls the
RegOpenKeyEx function, which simply opens an existing key and returns its handle in
phkResult, a parameter passed to the function by reference. Its syntax is:
Public Declare Function RegOpenKeyEx Lib "advapi32.dll" Alias "RegOpenKeyExA" _ (ByVal hKey As Long, _ ' Handle of already open key ByVal lpSubKey As String, _ ' Path from hKey to key to open ByVal ulOptions As Long, _ ' Reserved, must be 0 ByVal samDesired As Long, _ ' SAM constant(s) phkResult As Long) As Long ' Handle of newly opened key
RegKeyExists function then examines the value of the
phkResult argument to determine whether the key exists. If its value is non-zero, the
phkResult argument has been assigned a valid handle value, indicating that the key exists. The example function can then return
Otherwise, it returns
False. Instead of examining the value of the
phkResult parameter, the example function could have examined the value returned by the
RegOpenKeyEx function call. A value of
ERROR_SUCCESS indicates that the key exists, so the function should return True; any other value indicates that it does not exist.
RegKeyExists function, if it determines that the key exists, calls the Win32
RegCloseKey function to close the opened key. Its syntax is:
hKey is the handle to the registry key to close. Since handles to registry keys are system resources, calling the
RegCloseKey function when the handle is no longer needed is good programming practice.
Rather than calling
RegOpenKeyEx, an earlier and simpler version of the function,
RegOpenKey, can be called instead.
The function was introduced as part of the Win16 API, when Windows was predominantly a single-user desktop operating system and system security was considered relatively unimportant, and so lacks the
samDesired parameter. As a result, the function often returns
ERROR_ACCESS_DENIED when the default security access mask used by the function exceeds the permissions required by the key. Because of this, using
RegOpenKeyEx in the long run is simpler and more convenient.
Opening or Creating a Registry Key
Often when accessing the registry, you don't really care whether or not a key exists. Instead, you wish to open it if it exists and create it if it does not. This is often the case, for instance, when a new user first runs your application on a system configured to support multiple users. For this purpose, you use the
RegCreateKeyEx function, which opens an existing registry key or, if the key does not exist, creates it. Its syntax is:
Public Declare Function RegCreateKeyEx Lib "advapi32.dll" Alias "RegCreateKeyExA" _ (ByVal hKey As Long, _ ' Handle of already open key ByVal lpSubKey As String, _ ' Path from hkey to key to open/create ByVal Reserved As Long, _ ' Reserved, must be 0 ByVal lpClass As String, _ ' Reserved, must be a null string ByVal dwOptions As Long, _ ' Type of key, or backup/restore ByVal samDesired As Long, _ ' SAM constant(s) lpSecurityAttributes As SECURITY_ATTRIBUTES, _ phkResult As Long, _ ' Handle of opened/created key lpdwDisposition As Long) As Long '
Although most of these parameters need no explanation, several are not so obvious. The
dwOptions parameter determines the type of key to be created if
lpSubKey does not exist. Possible values are:
Public Const REG_OPTION_BACKUP_RESTORE = 4 Public Const REG_OPTION_NON_VOLATILE = 0 Public Const REG_OPTION_VOLATILE = 1
Non-volatile keys are saved as part of the registry, while volatile keys are not.
REG_OPTION_BACKUP_RESTORE indicates that
RegCreateKeyEx is called as part of a registry backup/restore operation and if necessary overrides the
samDesired parameter to provide for the necessary access.
If the function succeeds, the operation it performed is indicated by the
lphDisposition parameter, which is passed by reference to the function. Its value can be either of the following two constants:
Public Const REG_CREATED_NEW_KEY = &H1 ' A new key was created Public Const REG_OPENED_EXISTING_KEY = &H2 ' An existing key was opened
The function also includes a parameter of type
SECURITY_ATTRIBUTES, which is defined as follows:
Public Type SECURITY_ATTRIBUTES nLength As Long lpSecurityDescriptor As Long bInheritHandle As Long End Type
SECURITY_ATTRIBUTES type includes a security descriptor and determines whether the handle returned by the function call can be inherited. If we pass a
Null as the value of the pointer to the security descriptor, a newly created registry key will be assigned the default security descriptor of the current process. Assuming that this is adequate, we can define this argument in either of two ways:
Dim sa As SECURITY_ATTRIBUTES or Dim sa As SECURITY_ATTRIBUTES sa.nLength = Len(sa) sa.bInheritHandle = CLng(True)
The code to either open or create a subkey of
Software\MyCompany\MyCorporateApp is as follows:
Dim lResult As Long Dim hTopKey As Long, hKey As Long, lDisposition As Long Dim sRegPath As String Dim sa As SECURITY_ATTRIBUTES hTopKey = HKEY_CURRENT_USER sRegPath = "Software\MyCompany\MyCorporateApp" sa.nLength = Len(sa) sa.bInheritHandle = CLng(True) lResult = RegCreateKeyEx(hTopKey, sRegPath, 0, vbNullString, REG_OPTION_NON_VOLATILE, _ KEY_ALL_ACCESS, sa, hKey, lDisposition) If lResult = ERROR_SUCCESS Then If lDisposition = REG_CREATED_NEW_KEY Then ' Assign default values ElseIf lDisposition = REG_OPENED_EXISTING_KEY Then ' Retrieve values from existing keys End If Else MsgBox "Error " & lResult End If