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

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):

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

Note: 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 want 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:

  • 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. To obtain the actual value, you then pass that name to the RegistryKey::GetValue method:
Note: 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

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 then can 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:

Note: 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 because 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();
}


About the Author

Tom Archer - MSFT

I am a Program Manager and Content Strategist for the Microsoft MSDN Online team managing the Windows Vista and Visual C++ developer centers. Before being employed at Microsoft, I was awarded MVP status for the Visual C++ product. A 20+ year veteran of programming with various languages - C++, C, Assembler, RPG III/400, PL/I, etc. - I've also written many technical books (Inside C#, Extending MFC Applications with the .NET Framework, Visual C++.NET Bible, etc.) and 100+ online articles.

Downloads

Comments

  • #using

    Posted by jov0708 on 02/08/2008 12:43am

    hi, i'm using VS2003 and i'm making an MFC application that writes to the registry. however, my app showed an error "managed targeted code #using and /clr option" when declaring "#using ". what maybe the reason for this and how to solve it? thank you in advance... jov

    Reply
  • how can we do in VC++6.0?

    Posted by omshivaprasad2 on 06/26/2005 01:00am

    ur article is good, may i know how to do the same in vc++6.0

    • Answer

      Posted by Tom Archer on 06/26/2005 08:27am

      There are many articles on accessing the Registry in VC6. Just google for CRegistry and you'll find a few.

      Reply
    Reply
Leave a Comment
  • Your email address will not be published. All fields are required.

Top White Papers and Webcasts

  • Java developers know that testing code changes can be a huge pain, and waiting for an application to redeploy after a code fix can take an eternity. Wouldn't it be great if you could see your code changes immediately, fine-tune, debug, explore and deploy code without waiting for ages? In this white paper, find out how that's possible with a Java plugin that drastically changes the way you develop, test and run Java applications. Discover the advantages of this plugin, and the changes you can expect to see …

  • The first phase of API management was about realizing the business value of APIs. This next wave of API management enables the hyper-connected enterprise to drive and scale their businesses as API models become more complex and sophisticated. Today, real world product launches begin with an API program and strategy in mind. This API-first approach to development will only continue to increase, driven by an increasingly interconnected web of devices, organizations, and people. To support this rapid growth, …

Most Popular Programming Stories

More for Developers

Latest Developer Headlines

RSS Feeds