Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / Languages / VB

A Small Class Providing Typed Access To The Registry

3.78/5 (7 votes)
28 May 2006CPOL3 min read 1   534  
The described class allows to write/read values of various types to/from the Windows registry.

Sample Image - TypedRegistry_Image.png

Introduction

When I migrated to .NET from Borland Delphi, I felt a lack in the standard RegistryKey class. There are methods like WriteCurrency, WriteDate, and WriteBinaryData in Delphi's TRegistry class. Some useful methods working with the RegistryValueKind enumeration were added in .NET 2.0. But there is still a problem: how, for example, to save a value of the System.Decimal type in a registry key. The TypedRegistry assembly contains a class which allows to write and read data of the following types to/from a registry key: String, Byte[], Int32, Boolean, DateTime, Decimal, Double, Guid, Int64.

Though this is possible with .NET 2.0, the values are never saved using the REG_QWORD format (introduced in Windows 2000) because .NET 1.1 has no support for such a format. The TypedRegistry assembly was aimed for both .NET versions (1.1 and 2.0). So, all 8-byte values of the DateTime, Double, and Int64 types are saved as byte arrays.

AcedRegistry Class

C#
public class AcedRegistry : IDisposable

Provides methods for writing/reading typed data to/from the registry.

C#
public AcedRegistry(AcedRootKey registryRootKey, string registryKey, bool writable)

Opens a root registry key (such as HKEY_CURRENT_USER or HKEY_LOCAL_MACHINE) specified by the registryRootKey parameter. Then, opens a key passed as string via the registryKey parameter. If the value of the writable parameter is false, the registry key is opened in read-only mode. If that value is true, the registry key is opened (or created, if not exists) in read-write mode.

For example, you may pass the AcedRootKey.LocalMachine value in the first parameter, and the @"Software\CompanyName\ApplicationName" string in the registryKey parameter. The following is the list of possible values for the registryRootKey parameter. Each value corresponds to an instance of the root key exposed by the Microsoft.Win32.Registry class:

  • AcedRootKey.ClassesRoot
  • AcedRootKey.CurrentConfig
  • AcedRootKey.CurrentUser
  • AcedRootKey.DynData
  • AcedRootKey.LocalMachine
  • AcedRootKey.PerformanceData
  • AcedRootKey.Users
C#
public Microsoft.Win32.RegistryKey RegistryKey { get; }

Gets the related instance of the Microsoft.Win32.RegistryKey class. This property returns null if there is an error during opening or creating a registry key in the constructor of this class.

C#
public void Dispose()

Closes the related registry key, and flushes it to disk if its contents have been modified.

C#
public void Put(string valueName, String value)
public void Put(string valueName, Byte[] value)
public void Put(string valueName, Int32 value)
public void Put(string valueName, Boolean value)
public void Put(string valueName, DateTime value)
public void Put(string valueName, Decimal value)
public void Put(string valueName, Double value)
public void Put(string valueName, Guid value)
public void Put(string valueName, Int64 value)

Writes the value to the open registry key, with the value name specified by the first parameter (valueName).

C#
public bool Get(string valueName, ref String value)
public bool Get(string valueName, ref Byte[] value)
public bool Get(string valueName, ref Int32 value)
public bool Get(string valueName, ref Boolean value)
public bool Get(string valueName, ref DateTime value)
public bool Get(string valueName, ref Decimal value)
public bool Get(string valueName, ref Double value)
public bool Get(string valueName, ref Guid value)
public bool Get(string valueName, ref Int64 value)

Reads a value of the corresponding type with the specified name (valueName) from the open registry key. It is then returned in the value parameter. The method returns true if the value was successfully read. If there is no value with such a name in the current registry key, the method returns false, and does not modify the value parameter.

C#
public String GetDef(string valueName, String defaultValue)
public Byte[] GetDef(string valueName, Byte[] defaultValue)
public Int32 GetDef(string valueName, Int32 defaultValue)
public Boolean GetDef(string valueName, Boolean defaultValue)
public DateTime GetDef(string valueName, DateTime defaultValue)
public Decimal GetDef(string valueName, Decimal defaultValue)
public Double GetDef(string valueName, Double defaultValue)
public Guid GetDef(string valueName, Guid defaultValue)
public Int64 GetDef(string valueName, Int64 defaultValue)

Reads a value of the corresponding type with the specified name (valueName) from the open registry key, and returns that value as the method's result. If there is no value with such a name in the related registry key, the method returns a value of the defaultValue parameter.

Example of Usage

The following is a code fragment which saves and loads the program configuration as a set of values in the registry key:

C#
private const string
    DemoRegistryKeyName = "Software\\TypedRegistryDemo",
    cfgStringValueName = "StringValue",
    cfgDateTimeValueName = "DateTimeValue",
    cfgDecimalValueName = "DecimalValue",
    cfgBooleanValueName = "BooleanValue",
    cfgEnumValueName = "EnumerationElement",
    cfgByteArrayValueName = "Image";

private static string _stringValue;
private static DateTime _dateTimeValue;
private static decimal _decimalValue;
private static bool _booleanValue;
private static MyColors _enumValue;
private static byte[] _byteArrayValue;

private static void SaveConfig()
{
    using (AcedRegistry config = 
           new AcedRegistry(AcedRootKey.CurrentUser,
                            DemoRegistryKeyName, true))
    {
        config.Put(cfgStringValueName, _stringValue);
        config.Put(cfgDateTimeValueName, _dateTimeValue);
        config.Put(cfgDecimalValueName, _decimalValue);
        config.Put(cfgBooleanValueName, _booleanValue);
        config.Put(cfgEnumValueName, (int)_enumValue);
        config.Put(cfgByteArrayValueName, _byteArrayValue);
    }
}

private static void LoadConfig()
{
    using (AcedRegistry config = new AcedRegistry(AcedRootKey.CurrentUser,
        DemoRegistryKeyName, false))
    {
        config.Get(cfgStringValueName, ref _stringValue);
        config.Get(cfgDateTimeValueName, ref _dateTimeValue);
        config.Get(cfgDecimalValueName, ref _decimalValue);
        config.Get(cfgBooleanValueName, ref _booleanValue);
        _enumValue = (MyColors)config.GetDef(cfgEnumValueName, (int)_enumValue);
        config.Get(cfgByteArrayValueName, ref _byteArrayValue);
    }
}

It is convenient to enclose all method calls which access the registry into the using statement. Thus, we can be sure that the instance of the AcedRegistry class will be disposed at the end and the related instance of the standard RegistryKey class will be closed.

We can even save a value of a custom enumeration type in the registry as a value of the System.Int32 (or maybe System.Int64) type. In the above code fragment, we cast a value of the MyColors enumeration type to int before passing it to the Put method. Then, we cast it back to the MyColors type when the value is returned from the GetDef method.

Conclusion

The described class contains several methods to work with registry data in a typed manner. This is just an add-on over the standard RegistryKey class. To access the related RegistryKey while working with this class, please use the property of the same name.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)