The Windows Registry in C#

In this article I will explain you about the Windows Registry in C#.


This article has been excerpted from book "The Complete Visual C# Programmer's Guide" from the Authors of C# Corner.

The Windows registry acts as a central repository of information for the operating system and the applications on a computer. This database is organized in a hierarchical format, based on a logical ordering of the elements stored within it. When storing information in the registry, select the appropriate location based on the type of information being stored. Be sure to avoid destroying information created by other applications because this can cause those applications to exhibit unexpected behavior and can adversely affect your own application. 

Windows NT, 2000, and XP provide two versions of a Registry Editor: Regedt32.exe and Regedit.exe. Regedt32.exe is automatically installed in the %systemroot%\System32 folder. Regedit.exe is automatically installed in the %systemroot% folder. You can modify the registry using either of these Registry Editor utilities. However, if possible, you should use other utilities and tools provided with Windows 2000 to modify your system settings, such as those in the Control Panel. When you modify the registry with Registry Editor, the editor does not check for syntax or other errors. In addition, one modification to the registry may cause a cascade of changes throughout it. The results of an incorrect edit made with Registry Editor are unpredictable and may impair or disable the Windows 2000 operating system. However, by using other tools and utilities, you can ensure that modifications made to the registry are logical and valid, and you can manage any subsequent cascade of changes an edit may cause. 

You can use Regedt32.exe in read-only mode (on the Options menu, click Read Only Mode) to safely view the registry and not inadvertently make changes. Switch off read-only mode when you are certain of the changes you wish to make. 

Registry keys are the base unit of organization in the registry; they can be compared to folders in Windows Explorer. A particular key can have subkeys (just as a folder can have subfolders). Each key can also have multiple values associated with it, which are used to store information about your application. Each value holds one particular piece of information, which can be retrieved and updated when required. For instance, you can create a registry key for your company under the key HKEY_LOCAL_MACHINE\Software and then a subkey for each application that your company creates. Each subkey holds information specific to that application such as color settings, screen location, and product-specific file extensions. 

The information stored in the registry is available to other applications and users, and therefore you should not use the registry to store security or critical application information. The main base Registry categories for the Microsoft operating systems are as follows:

  • CurrentUser. Stores information about user preferences.
  • LocalMachine. Stores configuration information for the local machine.
  • ClassesRoot. Stores information about types (and classes) and their properties.
  • Users. Stores information about the default user configuration.
  • PerformanceData. Stores performance information for software components.
  • CurrentConfig. Stores non-user-specific hardware information.
  • DynData. Stores dynamic data.

The Registry class has a static field corresponding to each of these key types. The Registry class members are described as follows:

  • ClassesRoot. Returns a RegistryKey type that provides access to the HKEY_CLASSES_ROOT key.
  • CurrentConfig. Returns a RegistryKey type that provides access to the HKEY_CURRENT_CONFIG key.
  • CurrentUser. Returns a RegistryKey type that provides access to the HKEY_CURRENT_USER key.
  • DynData. Returns a RegistryKey type that provides access to the HKEY_DYN_DATA key.
  • LocalMachine. Returns a RegistryKey type that provides access to the HKEY_LOCAL_MACHINE key.
  • PerformanceData. Returns a RegistryKey type that provides access to the HKEY_PERFORMANCE_DATA key.
  • Users. Returns a RegistryKey type that provides access to the HKEY_USERS key.

For example, if you want to access the HKEY_LOCAL_MACHINE key, you need to call the Registry.LocalMachine member that returns a RegistryKey instance pointing to the local machine key. 

        RegistryKey pRegKey = Registry.LocalMachine;

The RegistryKey class enables you to manipulate data in a registry key; it contains members to add, remove, replace, and read registry data. Some of its common methods and properties are defined in Table 21.9. 

table21.9.gif

Table 21.9: Registry Class 

Let's see how to use these methods to add, remove, and update keys and their values. First we will add a subkey called HKEY_LOCAL_MACHINE/Software/MCBInc and place a value entry and a value inside (see Listing 21.18). 

Let's perform some actions against the registry. We can use CreateSubKey to add a new key to the Registry and call the SetValue method to write a value and key. The code in Listing 21.18 does this for us. The second parameter of the OpenSubKey method is a Boolean that identifies whether our access is for reading or writing. Use false in the second parameter for reading a value, and use true for writing a value. That way you can prevent unplanned, unwanted write operations. The public void SetValue (string name, object value) function sets the specified value to the registry key. The key must be opened for write access, and the key name is not case sensitive. Values allowed in the registry must be of the type DWORD, binary, or string. You pass these object types as the second parameter to the SetValue method, which accepts Object as the parameter type. You should format your string values appropriately before setting their values. String values can be represented in the following categories in the registry:

  • SZ. Data is represented as a null-terminated Unicode string value.
  • MULTI_SZ. Data is represented as an array of null-terminated Unicode strings.
  • EXPANDED_SZ. Data is represented as a null-terminated Unicode string with expanded references to environment variables.

Since many values can be stored in each key in the registry, the name parameter specifies the particular value you wish to manipulate. To set the default value for a particular registry key, the name can be set to either a null reference or an empty string (""). Notice in Listing 21.18 that the second parameter to OpenSubKey is set to true to enable the registry writing operation on that key. 

Listing 21.18: Using CreateSubKey and SetValue 

using System;
using Microsoft.Win32;

namespace TheWindowsRegistryCSharp
{
    class Program
    {
        static void Main(string[] args)
        {
           // Create a new key under HKEY_LOCAL_MACHINE\Software as MCBInc
            RegistryKey key = Registry.LocalMachine.OpenSubKey("Software", true);

            // Add one more sub key
            RegistryKey newkey = key.CreateSubKey("MCBInc");

            // Set value of sub key
            newkey.SetValue("MCBInc", "NET Developer");
        }
    }
}

The GetValue method returns the value of a subkey in the form of an object. In the example in Listing 21.19, we read the value of the CenteralProcessor\0 subkey and write it to the console. To get the default value for a particular registry key, set the name of the value in GetValue to either a null reference or an empty string (""). 

Listing 21.19: Using GetValue 

using System;
using Microsoft.Win32;

namespace TheWindowsRegistryCSharp
{
    class Program
    {
        static void Main(string[] args)
        {
            // Retrieve data from other part of the registry
            // find out your processor
            RegistryKey pRegKey = Registry.LocalMachine;
            pRegKey = pRegKey.OpenSubKey(@"HARDWARE\DESCRIPTION\System\CentralProcessor\0");
            Object val = pRegKey.GetValue("VendorIdentifier");
            Console.WriteLine("The central processor of this machine is:" + val);
        }
    }
}

You can also loop through all the subkeys inside a registry key by getting a collection of the subkeys as shown in Listing 21.20. 

Listing 21.20: Using GetSubkeyNames 

using System;
using Microsoft.Win32;

namespace TheWindowsRegistryCSharp
{
    class Program
    {
        static void Main(string[] args)
        {
            RegistryKey regkey = Registry.LocalMachine.OpenSubKey(@"Software\Mindcracker", false);

            foreach (String s in regkey.GetSubKeyNames())
            Console.WriteLine(s);
        }
    }
}

Furthermore, you can loop through all the values of the registry key by getting a collection of all the values in the key, as Listing 21.21 demonstrates. 

Listing 21.21: Using GetValueNames 

            //retrieve the array of values for that key
            String[] sarray = regkey.GetValueNames();

            //write the values to the screen
            foreach (String s in sarray)
            Console.WriteLine(s);

If you want to delete a key, use the DeleteSubKey or the DeleteSubKeyTree methods. The RegistryKey.DeleteSubKey method deletes the specified subkey. The RegistryKey.DeleteSubKeyTree method deletes a subkey, its data, and all of its child subkeys recursively in one shot. If you want to delete a value, use the DeleteValue method of the RegistryKey class. The RegistryKey.DeleteValue method deletes the specified value from the key. These methods are illustrated in Listing 21.22. 

Listing 21.22: Using DeleteValue and DeleteSubKey 

// Deleting registry keys and values
// Delete the key value

using System;
using Microsoft.Win32;

class Class1
{
    static void Main(string[] args)
    {
        // Create a new key under HKEY_LOCAL_MACHINE\Software as MCBInc
        RegistryKey key = Registry.LocalMachine.OpenSubKey("Software", true);

        // Add one more sub key
        RegistryKey newkey = key.CreateSubKey("MCBInc");

        // Set value of sub key
        newkey.SetValue("MCBInc", "NET Developer");

        // Retrieve data from other part of the registry
        // find out your processor
        RegistryKey pRegKey = Registry.LocalMachine;
        pRegKey = pRegKey.OpenSubKey("HARDWARE\\DESCRIPTION\\System\\CentralProcessor\\0");
        Object val = pRegKey.GetValue("VendorIdentifier");
        Console.WriteLine("The central processor of this machine is:" + val);

        // Delete the key value

        RegistryKey delKey = Registry.LocalMachine.OpenSubKey("Software", true);
        delKey.DeleteSubKey("MCBInc");
    }
}

There is another useful way to retrieve top-level registry handles (an alternative to the direct OpenSubKey method) for both local and remote computers. We can use the OpenRemoteBaseKey method: 

        RegistryKey rgkey = RegistryKey.OpenRemoteBaseKey(RegistryHive.LocalMachine, "MCBcomputer"); 

RegistryHive values are used by the OpenRemoteBaseKey method to represent the top-level node of a requested key on a foreign (remote) machine. The only nodes that can be opened with the OpenRemoteBaseKey method must be among the following top-level RegistryKeys. Further access to the subkeys of the identified node is available using methods in the RegistryKey class as long as the user has appropriate permission. 

ClassesRoot: Represents the HKEY_CLASSES_ROOT base key on a foreign machine. This value can be passed to the OpenRemoteBaseKey method, to open this node remotely. 

CurrentConfig: Represents the HKEY_CURRENT_CONFIG base key on a foreign machine. This value can be passed to the OpenRemoteBaseKey method, to open this node remotely. 

CurrentUser: Represents the HKEY_CURRENT_USER base key on a foreign machine. This value can be passed to the OpenRemoteBaseKey method, to open this node remotely. 

DynData: Represents the HKEY_DYN_DATA base key on a foreign machine. This value can be passed to the OpenRemoteBaseKey method, to open this node remotely. 

LocalMachine: Represents the HKEY_LOCAL_MACHINE base key on a foreign machine. This value can be passed to the OpenRemoteBaseKey method, to open this node remotely. 

PerformanceData: Represents the HKEY_PERFORMANCE_DATA base key on a foreign machine. This value can be passed to the OpenRemoteBaseKey method, to open this node remotely. 

Users: Represents the HKEY_USERS base key on a foreign machine. This value can be passed to the OpenRemoteBaseKey method, to open this node remotely. 

Listing 21.24 shows an example of reading some registry values on a foreign machine. Note that OpenRemoteBaseKey is opening the HKEY_LOCAL_MACHINE registry key on the machine named "ComputerNAME". Also note that OpenSubKey may not need a second Boolean parameter to indicate whether we are reading or writing to the registry because the single parameter call to OpenSubKey is read-only. 

Listing 21.24: OpenRemoteBaseKey Illustrated (reg2.cs) 

// Processor and Bios Information
using System;
using Microsoft.Win32;

public class MyRegistry
{
    static void Main()
    {
        RegistryKey hklm = Registry.LocalMachine;

        //or for a remote machine
        // RegistryKey hklm = RegistryKey.OpenRemoteBaseKey(RegistryHive.LocalMachine,"ComputerNAME");
        hklm = hklm.OpenSubKey(@"HARDWARE\DESCRIPTION\System\CentralProcessor\0");
        Object obp = hklm.GetValue("Identifier");
        Console.WriteLine("Processor Identifier :{0}", obp);
        hklm = Registry.LocalMachine;
        hklm = hklm.OpenSubKey(@"HARDWARE\DESCRIPTION\System\CentralProcessor\0");
        obp = hklm.GetValue("VendorIdentifier");
        Console.WriteLine("Vendor Identifier :{0}", obp);
        hklm = Registry.LocalMachine;
        hklm = hklm.OpenSubKey(@"HARDWARE\DESCRIPTION\System\MultiFunctionAdapter\4");
        obp = hklm.GetValue("Identifier");
        Console.WriteLine("Bios Status :{0}", obp);
        hklm = Registry.LocalMachine;
        hklm = hklm.OpenSubKey(@"HARDWARE\DESCRIPTION\System\");
        obp = hklm.GetValue("SystemBiosDate");
        Console.WriteLine("Bios Date :{0}", obp);
        hklm = Registry.LocalMachine;
        hklm = hklm.OpenSubKey(@"HARDWARE\DESCRIPTION\System\");
        obp = hklm.GetValue("Identifier");
        Console.WriteLine("System Identifer :{0}", obp);
    }
}

Conclusion

Hope this article would have helped you in understanding the Windows Registry in C#. See other articles on the website on .NET and C#.

visual C-sharp.jpg
The Complete Visual C# Programmer's Guide covers most of the major components that make up C# and the .net environment. The book is geared toward the intermediate programmer, but contains enough material to satisfy the advanced developer.