The “old-timers” among us remember the days before the Windows registry, when applications stored configuration information between executions in text-based INI files. A few years ago, things changed (better or worse is a matter of opinion) when Microsoft told us developers that INI files were bad—so bad, in fact, that we should stop using them and start using this new thing called the registry. The registry was complicated, though, especially for VB6 developers, who, being afflicted with the cruel joke known as the SaveSetting and GetSetting functions, often had to resort to Win32 API registry functions to use it effectively.
Now, with the advent of .NET, those of us on planet Microsoft who are interested in using the registry have an easier time of it. The .NET class library includes a set of classes, Microsoft.Win32.Registry and Microsoft.Win32.RegistryKey, that provide intuitive wrappers for the Win32 registry access functions. Before looking at these classes in detail, let’s step back a bit and see how the registry is organized and how you’d typically use it in an application.
Breaking out in hives
If you’ve never worked with the registry before, it's best to think of it as you would the file system on a disk. You have folders, which translate to keys in the registry, subfolders (subkeys), and files (values). Each subkey may contain one or more named values, which are the actual data storage areas of the registry.
This analogy is useful as long as you realize that, while a disk will have a single root directory, the registry has several root keys, which are collectively referred to as hives. The number and names of these root keys will vary somewhat depending on which version of Windows you’re running. The hives found on Windows NT-based OSs are shown in Figure A.
Most of the time, your work with the registry will fall into one of three categories:
- Checking to see whether a specific key exists
- Retrieving a value under a particular key
- Saving a value under a particular key for later retrieval
Of these, the final two tasks will usually mean accessing keys located under subkeys of the HKEY_Local_Machine\Software key, which involves first navigating to the appropriate subkey and then locating and manipulating the appropriate value by name. Navigation to a subkey always begins with its root hive. For example, to access a subkey named MyKey found under HKEY_Local_Machine\Software, you’d open the subkey HKEY_Local_Machine\Software\MyKey and then work with any of the values it contains.
Start at the hives to access subkeys
The Registry class serves as the entry point to the registry by providing you with access to the root hives. Registry exposes seven static RegistryKey members, one for each of the hives you met in Figure A, plus one representing a Win9x-only hive: HKEY_Dyn_Data, which holds dynamic registry data not stored on disk. See Figure B for a look at how these static members map to the registry hives.
The RegistryKey class provides the methods you’ll use to navigate in the registry and access named values. The class’s OpenSubKey method accepts the case-insensitive name of a subkey, along with a Boolean value indicating whether the key should be opened for read-write access. It returns a new RegistryKey object representing the opened subkey. OpenSubKey also works when given a relative path to the subkey. (Just remember to properly escape backslashes as \\.) If the subkey doesn’t exist, OpenSubKey returns null/Nothing. Always remember to close an open subkey using the Close method.
To extend the above example, the VB.NET code to open HKEY_Local_Machine\Software\MyKey for read/write access would look like this:
Dim k as RegistryKey
k = Registry.LocalMachine.OpenSubKey(“Software\\MyKey”
Reading and storing values
The GetValue and SetValue methods provide access to any named values found under a key. Although registry values are strongly typed, the .NET runtime does all the conversions for you, so you really don’t have to worry about type matching. GetValue is overloaded to allow you to specify a default value to return should the named value not exist, and it should go without saying that SetValue will fail if a key is opened without write access. Extending the above example a little further, suppose we want to retrieve the numeric “ValueA” and save a string as “ValueB” under the MyKey subkey I opened above:
Dim j as Integer
k.SetValue(“ValueB”, “String Value”)
j = k.GetValue(“ValueA”)
Here’s the code to accomplish the same thing in C#:
RegistryKey k = Registry.LocalMachine.OpenSubKey(
int j = k.GetValue(“ValueA”);
Unless you’ve had the…pleasure…of using the Win32 API to access the registry, you’ll likely not be able to truly appreciate how easy .NET makes it. In any event, you should have no excuses left for not using the registry to store your application’s configuration information.
Suggest additional topics
What other aspects of using the registry would you like to see explored on Builder.com? Send us an e-mail with your suggestions, or post them to the discussion below.