July 25, 2014
Hot Topics:
RSS RSS feed Download our iPhone app

Managed C++: Read and Write Registry Keys and Values

  • December 20, 2004
  • By Tom Archer
  • Send Email »
  • More Articles »
Programmatically accessing the Windows registry has always been a bit of a convoluted task. For this reason, a myriad C++ classes have been created over the years to enable easier and more intuitive access to the registry from Windows applications. Thankfully, the task of reading and writing registry keys and values is monumentally easier with the .NET framework.

This article illustrates the following common registry tasks (Figure 1 shows the mixed-mode MFC/.NET demo application supplied with this article):



Click here for a larger image.

Figure 1: The attached demo illustrates the most common tasks that involve programmatically accessing and modifying the Windows registry.

In order to use the following code snippets, you must include the namespace Microsoft::Win32 in your code and if you're writing a mixed-mode application, undefine MessageBox:
using namespace Microsoft::Win32;
#undef MessageBox

Enumerating a Registry Key's Subkeys

To understand how to enumerate a registry key, consider the basic example of enumerating the Software key in the HKEY_CURRENT_USER (HKCU) hive. The following are the basic steps for accomplishing that task:

  1. Instantiate a RegistryKey object using the static Registry::CurrentUser value. Note that you can access all of the standard root keys (hives) in this manner. For example, you can access the HKEY_CLASSES_ROOT via Registry::ClassesRoot, the HKEY_LOCAL_MACHINE via the Registry::LocalMachine, and so on.
  2. Instantiate a RegistryKey object representing the registry key you wish to work with (the Software key, in this case) via a call to the root key's RegistryKey::GetSubKey method.
  3. Open the registry key via a call to the RegistryKey::Open method.
  4. Retrieve the subkeys by calling the RegistryKey::GetSubKeyNames method. This method returns an array of subkey names (in the form of String objects).
  5. Iterate through the returned array, performing your own application-specific logic.
  6. Close any open RegistryKey objects via a call to the respective Close methods.

RegistryKey* currentUser;
RegistryKey* softwareKey;

try
{
  // Specify the HKEY_CURRENT_USER hive
  currentUser = Registry::CurrentUser;

  // Open the Software key
  softwareKey = currentUser->OpenSubKey(S"Software");

  // Request all subkeys from the Software key
  String* subkeys[] = softwareKey->GetSubKeyNames();

  // Enumerate the subkeys
  for (int i = 0; i < subkeys->Length; i++)
  {
    // Each subkey is now represented by subkeys[i]
  }
}
catch(Exception* ex)
{
  MessageBox::Show(ex->Message);
}
__finally
{
  if (softwareKey) softwareKey->Close();
  if (currentUser) currentUser->Close();
}

Enumerating a Registry Key's Values

The process for enumerating a registry key's value is almost identical to enumerating keys with the following differences:
  • In order to obtain the array of registry key value names, call the RegistryKey::GetValueNames method.
  • Each entry in the returned array is a String representing the value name. In order to obtain the actual value, you then pass that name to the RegistryKey::GetValue method:
The RegistryKey::GetValue method returns a base Object that you then cast to the appropriate type. Therefore, you need to know exactly what type you are expecting because there is no programmatic way of determining the value's type as defined in the registry (string, numeric, or binary value).
RegistryKey* currentUser;
RegistryKey* softwareKey;

try
{
  // Specify the HKEY_CURRENT_USER hive
  currentUser = Registry::CurrentUser;

  // Open the "Shell Folders" subkey
  softwareKey = currentUser->OpenSubKey(
    S"Software\\Microsoft\\Windows\\CurrentVersion\\"
    S"Explorer\\Shell Folders");

  // Request all values from the "Shell Folders" key
  String* valueNames[] = softwareKey->GetValueNames();

  // Enumerate the values
  for (int i = 0; i < valueNames->Length; i++)
  {
    // Each value name is now represented by valueNames[i]
    // The actual value is returned via the subkey's GetValue method like this:
    String* value = static_cast<String*>(softwareKey->GetValue(valueNames[i]));
  }
}
catch(Exception* ex)
{
  MessageBox::Show(ex->Message);
}
__finally
{
  if (softwareKey) softwareKey->Close();
  if (currentUser) currentUser->Close();
}

Creating a New Registry Key and Value

In order to create a new registry key, you simply need to call the RegistryKey::CreateSubKey method. This method returns a RegistryKey object representing the newly created key. You can then create that key's values via calls to the SetValue method. The following code snippet creates a new key under the HKCU/Software key called "My Product" and then adds values for Description and Version:
The CreateSubKey method will not throw an exception if it fails due to the subkey already existing. Instead, the method simply returns a value of null.
RegistryKey* currentUser;
RegistryKey* softwareKey;

try
{
  RegistryKey* currentUser = Registry::CurrentUser;
  RegistryKey* softwareKey = currentUser->CreateSubKey(S"Software\\My Product");

  softwareKey->SetValue(S"Description", S"Description of my product");
  softwareKey->SetValue(S"Version", S"1.42");
}
catch(Exception* ex)
{
  MessageBox::Show(ex->Message);
}
__finally
{
  if (softwareKey) softwareKey->Close();
  if (currentUser) currentUser->Close();
}

Modifying an Existing Registry Key and Value

This task is almost identical to creating values, with the only difference being that since the key already exists, you need to open the key (via RegistryKey::OpenSubKey) before calling the SetValue methods (The OpenSubKey method will return null if the key does not exist.):
RegistryKey* currentUser;
RegistryKey* softwareKey;

try
{
  RegistryKey* currentUser = Registry::CurrentUser;
  RegistryKey* softwareKey = currentUser->OpenSubKey(S"Software\\My Product", true);

  if (softwareKey)
  {
    softwareKey->SetValue(S"Description", S"Description of my product");
    softwareKey->SetValue(S"Version", S"1.42");
  }
}
catch(Exception* ex)
{
  MessageBox::Show(ex->Message);
}
__finally
{
  if (softwareKey) softwareKey->Close();
  if (currentUser) currentUser->Close();
}

Download the Code

To download the accompanying source code for the demo, click here.

About the Author

Tom Archer owns his own training company, Archer Consulting Group, which specializes in educating and mentoring .NET programmers and providing project management consulting. If you would like to find out how the Archer Consulting Group can help you reduce development costs, get your software to market faster, and increase product revenue, contact Tom through his Web site.






Comment and Contribute

 


(Maximum characters: 1200). You have characters left.

 

 


Sitemap | Contact Us

Rocket Fuel