Harness the power of the registry API in your VB apps

Let's face it. VB's built-in registry access is a big joke. But you can laugh last if you roll your own registry access using Windows' registry API. Lamont Adams shows you how.

In a previous article, I showed you two simple ways to use the registry from Visual Basic. But if you need to add a little octane to your registry tank, you can always turn to the Win32 API. It includes 30 functions for working with the registry. That's quite a few to choose from, and you can forget about most of them. Odds are, you won't need to know about more than six of these to be able to effectively use the local registry. Table A lists these important API functions.
Table A
Function Description
RegOpenKeyEx Opens a key given a relative path to it from a hive or previously opened key. It returns a handle that can be used with other registry API functions.
RegCreateKeyEx Creates a new key as a subkey of a hive or previously opened key and opens it. If the key already exists, it is opened instead. It returns a handle that can be used with other registry API functions.
RegCloseKey Closes a key
RegQueryValueEx Retrieves the data associated with a named value in a previously opened key. Call it with a value of 0 for lpData to determine the size and type of data in the value.
RegSetValueEx Saves data to a named value in a previously opened key. If the value does not already exist, it is created.
RegDeleteKey Deletes the specified key and all values and subkeys it contains
Ignore the rest of the functions; these are all you'll need.

The Visual Basic Declare statements for these functions, along with some useful constant definitions, such as predefined keys and registry data types, appear in Listing A. To see how these functions work, check out the code for the cRegAccess class in Listing B. The code encapsulates some of the API functions into a VB class. For brevity, I did not include the Declare statements and constants you'll find in Listing A; you'll just need to pretend that they are there.

A little warning
Some words of advice for you before you go off and start playing in your registry. If you mess with the wrong areas of the registry, like those that store critical system data, you run the risk of seriously hosing your system, so exercise due caution.

Registry data types revisited
The registry can handle data in 12 formats, and the registry API allows you to work with all of them. Of these 12, most are unlikely to be important to the average VB programmer. After all, when was the last time you ran across a number in big-endian format? Do you even know what that means without looking it up? I rest my case. Table B lists the available data formats and VB equivalents for those that have them.

Table B
Registry data types

The REG_SZ and REG_DWORD types can store simple string or numeric data, such as application configuration data. The use of either is relatively straightforward from VB. The REG_MULTI_SZ type stores a list of null-terminated strings (REG_SZ values), like the contents of a list box. Values of type REG_BINARY can be used to store small amounts of binary data, like serialized objects. Byte arrays will be your best friends when dealing with binary data.

Open, Set, Query, Close…rinse and repeat
Now that you've seen the relevant API functions and understand the data types you'll be dealing with, let's talk about the actual process of accessing the registry.

Before you can do anything with a registry key, you must open it with RegOpenKeyEx. You'll need to specify the path to a key (without the leading backslash) relative to one of the hives or to a key you opened previously. For example, to open the HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft key, we'd pass SOFTWARE\Microsoft for the lpSubKey parameter and the constant HKEY_LOCAL_MACHINE (that's –2147483646, if you are interested) as the hKey parameter. Assuming the call succeeds, you'll receive a handle to the Microsoft key as the phkResult output parameter. You can use this handle to open subkeys or access values found in the Microsoft key. Check out cRegAccess.OpenKey for an example of this.

Storing and retrieving data
Once you have a handle to an opened key, you can use the storage and retrieval functions, RegSetValueEx and RegQueryValueEx, respectively, to work with data in one or more of that key's values. Both of these functions accept the open key handle as the hKey argument. Again, this would be the phkResult output argument from your call to RegOpenKeyEx. You'll also need to specify the name of a value in hKey (lpValueName), the registry data type of the data stored there (lpType for Query, dwType for Set), a data variable (lpData), and the size of that variable (lpcbData for Query, cbData for Set).

To store data to the registry using RegSetValueEx, as demonstrated in the cRegAccess.SaveData method, you'd follow this basic process:
  1. 1.      Call RegOpenKeyEx to open a key.
  2. 2.      Call RegSetValueEx to store your data to a value.
  3. 3.      Call RegCloseKey to close the key when you are finished.

Note that if the value name you specify does not already exist in that key, RegSetValueEx will create a new value with that name and store your data into it.

The process to retrieve data, illustrated in cRegAccess.GetData, includes extra steps if you don't know the size and format of the data you will be dealing with. The basic steps here are:
  1. 1.      Call RegOpenKeyEx.
  2. 2.      Optionally, call RegQueryValueEx with an lpData argument of zero to determine the size and format of the data in the value or values you are interested in, if unknown.
  3. 3.      Call RegQueryValueEx to retrieve the data from the value or values you're interested in.
  4. 4.      Call RegCloseKey when you're finished.

Closing a key with RegCloseKey is straightforward. It accepts as its sole argument the handle of the key to be closed. You can see this exciting task performed yourself in cRegAccess.CloseKey, in Listing B.

Stupid registry tricks
The RegCreateKeyEx function is used to create new keys and works similarly to RegOpenKeyEx. It, too, needs a key handle, and it will create a new subkey under this key with the name you specify (lpSubKey), open the new key for you, and give you a handle to it through the phkResult output parameter. If you try to create a key that already exists, RegCreateKeyEx will simply open it for you. You can see RegCreateKeyEx in action in cRegAccess.CreateKey in Listing B.

How do you use the registry in your applications?
Is the registry just a glorified .INI file to you, or do you have a novel way of using it? Drop us a line and tell us about it.

If you are going to create keys, you will eventually have to delete them. The RegDeleteKey function will delete a named subkey of the key associated with the handle you pass it in the hKey argument. It will delete all values and subkeys of that subkey. There is no undo command for key deletions, so make sure you really mean it when you delete a key. In Listing B, cRegAccess.DeleteKey illustrates the usage of RegDeleteKey.

Where the registry meets the road
Here are a few words of parting advice. First, remember to be very careful when messing with the registry. You should know that already, but I still have to make it clear. Second, don't use the registry to store large amounts of data, as doing so can negatively affect the performance of the entire system. Microsoft recommends that data storage be limited to less than 2 KB of data. For larger amounts, store the data in a file someplace and use a registry entry to store the path to that file. Finally, make sure that your solution fits the problem: If all you need to do is store a few pieces of application information, the complexity of using the registry API may not be worth it.



Editor's Picks