Monday, March 16, 2009

Access Registry using Visual Basic

The Windows Registry s the central database of any Windows PC. This article explains the registry, and shows us how to access it using both Visual Basic's functions and the Windows API.

We could call it a central database, which stores all software and hardware related settings on your PC. The registry was introduced during the Windows 3.1 days but wasn't extensively used back then. However, in Windows 9x (and NT) the usage of the registry increased considerably. These days I wouldn't be surprised if I saw the size of anyones registry running into several megabytes.

The registry stores information in different categories, which are known as hives. The folders appearing on the left hand side of the registry are all hives. A hive may be further divided into keys. All of the information in the registry is divided into 6 major categories (or hives). Each hive may contain multiple keys and those keys may contain multiple sub-keys. Now let's look at what information these different hives (or categories) contain:

1. HKEY_CLASSES_ROOT
Stores information about the DLL's on the current computer. It also stores information about file extensions.

2. HKEY_CURRENT_USER
Stores information about the user who is currently logged on to the computer. Information stored includes environment variables, desktop settings, network configuration, etc.

3. HKEY_LOCAL_MACHINE
Stores information about the hardware and software configuration on the computer.

4. HKEY_USERS
Stores information about all users registered on the computer. Information stored includes environment variables, desktop settings, network configuration, etc.

5. HKEY_CURRENT_CONFIG
Stores information about the current hardware and software configuration on the computer.

6. HKEY_DYN_DATA
Stores information that changes frequently (dynamic information) on your computer. This includes thread/process details, plug and play, etc.

Functions To Access The Registry
You can access the registry a number of ways in Visual Basic. One of the ways is to use functions for interacting with the registry.

The SaveSetting Function
The SaveSetting function allows us to store any value in the registry. The functions signature looks like this:

SaveSetting ,
, ,

Application Name: The name of the application that's creating the key
Section: The section name under which this key is being created.
Key: The name of the key being created
Value: The value of the key being created

The following code snippet would add a key called TestKey in the registry to the HKEY_CURRENT_USER\Software\VB and VBA Program Settings\TestApp\TestSection path:

SaveSetting "TestApp", "TestSection", "TestKey", "TestVal"

The GetSetting Function
The GetSetting function allows us to retrieve any value from the registry. The usage of the GetSetting function looks like this:

GetSetting (,
, [, Default])

Application Name: The application name for which we are retrieving this key
Section: The section name under which this key is being stored
Key: The name of the key that we are creating
Default: The default value would be returned if the value of the key couldn't be retrieved. This is an optional parameter.

The following code snippet would retrieve the value of the key TestKey from the registry under the following path HKEY_CURRENT_USER\Software\VB and VBA Program Settings\TestApp\TestSection path:

Dim value As String
value = GetSetting("TestApp", "TestSection", "TestKey", "Default")
MsgBox value


"Default" would be displayed if no such entry was found.

The DeleteSetting Function

The DeleteSetting function allows us to delete any value/values from the registry. The signature of the DeleteSetting function looks like this:

DeleteSetting [,
[,]]

Application Name: The application name from which we are deleting keys
Section: Contains the keys you need to delete. This is an optional parameter
Key: The name of the key that you want to delete. This is an optional parameter

Private Sub DeleteRegistry()
DeleteSetting "TestApp"
DeleteSetting "TestApp2", "TestSection2"
DeleteSetting "TestApp3", "TestSection3", "TestKey3"
End Sub


Let's see exactly what the code above does:

Firstly, it would delete the entire TestApp key (including all sub-keys and values) under it from the HKEY_CURRENT_USER\Software\VB and VBA Program Settings\TestApp path.

Next, it would delete the entire TestSection2 key (which is a part of the TestApp2 key) and all sub-keys and values under it from the HKEY_CURRENT_USER\Software\VB and VBA Program Settings\TestApp2\TestSection2 path. However, the TestApp2 key and its contents wouldn’t be deleted.

Finally, it would delete the TestKey3 string value (which is a part of the TestApp3\TestSection3 keys). However the TestApp3 key and TestSection3 key (and their contents) wouldn't be deleted.

The GetAllSettings Function
The GetAllSettings function allows us to retrieve an entire collection of string values from the registry. Using this function, we can retrieve an entire set of string values from a particular section. The signature for the GetAllSettings function looks like this:

GetAllSettings (,
)

Application Name: The application key under which you need to retrieve the collection of string values
Section: The key to where the collections of values are present

Private Sub GetAllRegistry()
Dim valuesandkeys As Variant
Dim count As Integer

SaveSetting "Tester", "TestSec", "TestName1", "TestVal1"
SaveSetting "Tester", "TestSec", "TestName2", "TestVal2"

valuesandkeys = GetAllSettings("Tester", "TestSec")

For count = LBound(valuesandkeys) To UBound(valuesandkeys)
Key = valuesandkeys(count, 0)
value = valuesandkeys(count, 1)
MsgBox Key
MsgBox value
Next count
End Sub


Let's see exactly what the code above does:

Firstly, we add two string values into the registry under the HKEY_CURRENT_USER\Software\VB and VBA Program Settings\Tester\TestSec\ path.

Next, we call the GetAllSettings function which returns a two dimensional array of all keys and values in the HKEY_CURRENT_USER\Software\VB and VBA Program Settings\Tester\TestSec\ hive.

Finally, we use a simple for loop to display all of the values in the array. The first index in the array holds the name/key serial count. We would pass 0 as the next index if we wanted to display the string name and 1 if we wanted to trap the key string value. The structure of the two dimensional array looks like this:

0 1
0 TestName1 TestValue1
1 TestName2 TestValue2

Thus, if we pass the index 1,1 to the array, then it would return "TestValue2". If we pass the index 0,0 to the array then it would return "TestName1".

There are some points to remember when using Visual Basic functions to access the registry:
  1. This code wouldn't work if you didn’t have appropriate permissions to access the registry. Remember, whenever you run software on a computer that interacts with the registry, you have to make sure the logged in user has privileges to access the system registry or else your program will not function.
  2. The Visual Basic functions help us interact with the registry only under the following path "HKEY_CURRENT_USER\Software\VB and VBA Program Settings"..
  3. The Visual Basic functions are capable of retrieving and setting String keys only.

Using Windows API to Access the Registry

As you can see, there are some disadvantages to using Visual Basic's registry functions. For example, what if you needed to set/retrieve values from other parts of the registry? What if you need to set/retrieve binary or dword values from the registry? Well, in such cases you may have to use the Windows API to access the registry, which is what we will look at next.

Whenever we are going to use any API function, we need to declare it in our code. In our case, we would have to declare the following functions:

Public Declare Function RegCreateKey Lib "advapi32.dll" Alias "RegCreateKeyA" (ByVal hKey As Long, ByVal lpSubKey As String, phkResult As Long) As Long

Public Declare Function RegOpenKey Lib "advapi32.dll" Alias "RegOpenKeyA" (ByVal hKey As Long, ByVal lpSubKey As String, phkResult As Long) As Long

Public Declare Function RegDeleteKey Lib "advapi32.dll" Alias "RegDeleteKeyA" (ByVal hKey As Long, ByVal lpSubKey As String) As Long

Public Declare Function RegCloseKey Lib "advapi32.dll" Alias "RegCloseKey" (ByVal hKey As Long) As Long


Creating a Key
Lets create a function that uses the RegCreateKey API function internally to create a key anywhere in the registry:

Private Sub CreateNewKey()
Dim hNewKey As Long
Dim lRetVal As Long

lRetVal = RegCreateKey(HKEY_CURRENT_USER,"TestKey", hNewKey)
RegCloseKey (hNewKey)
End Sub


Let's look at what this code does.

First up, we call the RegCreateKey function and pass 3 parameters to it. Firstly, the hive in which we want to create the key. Secondly, the name of the key that we want to create under this hive, and finally, the key handle, which can be an empty long variable.

After this line is executed, the hNewKey long variable would contain a reference to the newly created key. This line would create a key right under the HKEY_CURRENT_USER hive. The successful execution of this line would return a long value, which we trap in the lRetVal variable.

Next up, we call the RegCloseKey function to close the reference that we have just created. This is done in order to free CPU resources. It's not a mandatory step, but should be done. It takes just one parameter, which is the key handle (or object) to be closed.

Deleting a Key
Let's code a function that uses the RegCreateKey API function internally to delete a key anywhere in the registry:

Private Sub Form_Load()
Dim lRetVal As Long
Dim hNewKey As Long

lRetVal = RegOpenKey(HKEY_CURRENT_USER, "", hNewKey)
lRetVal = RegDeleteKey(hNewKey, "Test")

RegCloseKey (hNewKey)
End Sub


Let's look at what this code does.

Firstly, we call the RegOpenKey function and pass 3 parameters to it: the hive in which we want to delete the key, the key path to delete, and the key handle.

After this line is executed, the hNewKey long variable would contain a reference to the key path specified in the RegOpenKey function. This line would create a reference to the HKEY_CURRENT_USER hive. The successful execution of this line would return a long value, which we trap in the lRetVal variable.

Secondly, we call the RegDeleteKey function and pass 2 parameters to it. Firstly, the reference to the hive we need to delete the key from. Secondly, the key path to delete. This line would delete the "Test" key under the HKEY_CURRENT_USER hive. It would also end up deleting all of its sub keys and values too. The successful execution of this line would return a long value, which we trap in the lRetVal variable.

Finally, we call the RegCloseKey function to close the reference we have just created. This is done in order to free CPU resources. This is not a mandatory step, but it should be done. It takes one parameter, which is the key handle to be closed.

No comments:

Post a Comment