Registry on Windows 64 Bit – Double Your Pleasure

For those of you who are new to windows 64 bit you’ll be happy to know that Microsoft decided to double our pleasure!
We now have TWO Registries, TWO Program Files directories and Two WindowsSystem folders.
That’s what I call developers fun. See this excellent post by Sasha 

I’ll focus here on the registry. 
Suppose we have a managed process that reference the following registry path
HKEY_LOCAL_MACHINESOFTWAREMyApp

When it runs as 64 bit process it will reference
HKEY_LOCAL_MACHINESOFTWAREMyApp 
When it runs as 32 bit process it will reference:
HKEY_LOCAL_MACHINESOFTWAREWow6432NodeMyApp

Now if your application can run both as 32 and 64 bit (Managed process can do that) and the process need to access the registry at run time you have two options:
Option one: Two entries in the registry.

Example:
Our process needs to set the value MyValue in the registry at run time.
You can write the following code:

RegistryKey key = Registry.LocalMachine.OpenSubKey(@”SOFTWAREMyApp”, true);

key.SetValue(“MyValue”, “123″);

key.Close();

Now when the process runs as 64 bit it will change the value under:
HKEY_LOCAL_MACHINESOFTWAREMyAppMyValue
When it runs as 32 bit the same code will change the value in different place:
HKEY_LOCAL_MACHINESOFTWAREWow6432NodeMyAppMyValue

This code forces you to create and use two different places in the registry which is really not pleasant. Suppose that you launch some kind of configuration utility which runs as 64 bit process the configuration set up a flag in the registry that sets the log to on.
Than you run an application that runs as 32 bit (MSTest for example)  the code that reads the flag will look for the flag under  Wow6432Node. Totally different place!

We found another solution for this mess.
Here are the rules:
1. 64 bit process have access to both Wow6432Node and 64 registries
2. 32 bit process access only to Wow6432Node registry.
3. Both can access the full path to the 32 bit e.g
HKEY_LOCAL_MACHINESOFTWAREWow6432NodeMyAppMyValue

The solution is to use only the Wow6432Node entry.
instead of:

RegistryKey key = Registry.LocalMachine.OpenSubKey(@”SOFTWAREMyApp”, true);

Use:

RegistryKey key = Registry.LocalMachine.OpenSubKey(@”SOFTWAREWow6432NodeMyApp”, true);

This code will work on 64 bit OS but will fail on 32 bit OS since it doesn’t have Wow6432Node.
Here is the final code that will run both on 32 and 64 bit OS:

RegistryKey key;

string keyPath = @”SOFTWARE\MyApp”;

// This is how we find the OS on run time

// on 32 bit OS IntPtr.Size = 4

// on 64 bit OS IntPtr.Size = 8   

if (IntPtr.Size == 8)

{

   keyPath = @”SOFTWAREWow6432NodeMyApp”;

}

key = Registry.LocalMachine.OpenSubKey(keyPath, true);

key.SetValue(“MyValue”, “123″);

key.Close();

  • hemp

    Checking the size of an IntPtr is useful, but insufficient for determining the executing OS’s target architecture. If you run the process under WOW64, the size of IntPtr will be 4. Correctly identifiying the OS architecture from .NET typically involves a P/Invoke to the IsWow64Process function when IntPtr.Size is 4.

  • Ohad

    Thanks for the correction.
    You are right of course. Having said that the code will work since the intention here is to always reference the 32 bit registry.

TOP