Things to keep in mind regarding Registry while migrating a 32 bit application from Vista x64 to Windows 7 x64

If you are migrating a 32 bit application from Vista x64 to Windows 7 x64 and your application relies on some information in registry. There are few things you should consider as following.

In Windows 7, registry is virtualized. As a result, wow64 applications don’t have to explicitly provide registry path with Wow6432Node node. For example if you have to probe 32 bit .Net SDK’s location, you don’t have to use path like path \SOFTWARE\Wow6432Node\Microsoft\.NETFramework from your 32 bit app. Using just \SOFTWARE\Microsoft\.NETFramework should direct your application to an entry under Wow6432Node.

For example, If you are using RegistryKey class in a 32 bit managed application running on 64 bit Win7 and something like

RegistryKey key = Registry.LocalMachine.OpenSubKey(@"\SOFTWARE\Wow6432Node\Microsoft\.NETFramework”;

You will be routed to \SOFTWARE\Wow6432Node\Wow6432Node \Microsoft\.NETFramework and get null key returned.

Let me show you an example.

Although, On Windows 7, it is not needed to check platform before reading and writing in registry but to make things clear, I am going to use a method called CheckArchitecture() , Depending upon the processor and AddressWidth property returned by System.Environment.GetEnvironmentVariable("PROCESSOR_ARCHITECTURE") and WMI, I am figuring if the process is pure x86, x64 or WOW64 (32 bit process on 64 bit operating system.

//Logic to check architecture and verified it using three flags (X86,X64 and SysWOW64). I called this Method CheckArchitecture()

public static string CheckArchitecture()// Return one of these values (X64, X86, SysWOW64, Unidentified)

{

     PropertyData PropData = null;

     string archi = null;

     string AddressWidth = null;

     // Check Process architecture (x86 or AMD64)

     string ProcessArchi = System.Environment.GetEnvironmentVariable("PROCESSOR_ARCHITECTURE");

     // Check process architecture

     ManagementObjectSearcher MObjCollection = new ManagementObjectSearcher("select * from Win32_Processor");

     foreach (ManagementObject MObj in MObjCollection.Get())

            {

       // AddressWidth = 64 means x64 OS, 32 means x86 OS

             PropData = MObj.Properties["AddressWidth"];

             if (PropData.Name != null && PropData.Value != null) // Check to avoid null reference.

                    {

       //Console.WriteLine(PropData.Name.ToString() + " = " + PropData.Value.ToString());

                     AddressWidth = PropData.Value.ToString();

                    }

             }

       // Check combination of ProcessArchi and AddressWidth

              if (ProcessArchi == "AMD64" && AddressWidth == "64")

                {

                    archi = "X64";

                }

                else if (ProcessArchi == "x86" && AddressWidth == "64")

                {

                    archi = "SysWOW64";

                }

                else if (ProcessArchi == "x86" && AddressWidth == "32")

                {

                    archi = "X86";

                }

                else

                {

                    archi = "Unidentified";

                }

            return archi;

}

 

 

In this sample code I am calling my CheckArchitecture() method above.

 

RegistryKey key; // I am not opening registry right now.

// This should print Architecture value

Console.WriteLine("Architecture = " + CheckArchitecture());

string platform = CheckArchitecture();

// Called the method to check architecture.

string dbPath = string.Empty;

try

      {

          if (platform.ToString() == "X86")

          {

// NOTE : No Wow6432Node in Key path

           key = Registry.LocalMachine.OpenSubKey(@"Software\Microsoft\.NETFramework", RegistryKeyPermissionCheck.ReadSubTree, System.Security.AccessControl.RegistryRights.ReadKey);

//Output : Screenshot 1 at bottom

          }

          else if (platform.ToString() == "X64")

          {

           key = Registry.LocalMachine.OpenSubKey(@"Software\Microsoft\.NETFramework", RegistryKeyPermissionCheck.ReadSubTree, System.Security.AccessControl.RegistryRights.ReadKey);

//Output : Screenshot 2 at bottom

          }

           else if (platform.ToString() == "SysWOW64")

// Additional check. This is 32 bit process on 64 bit OS and CPU.

          {                  

// NOTE : No Wow6432Node in Key path                   

key = Registry.LocalMachine.OpenSubKey(@"Software\Microsoft\.NETFramework", RegistryKeyPermissionCheck.ReadSubTree, System.Security.AccessControl.RegistryRights.ReadKey);

//Output : Screenshot 3 at bottom

}

                else

                {

                    throw new Exception("Unknown OS version ..");

                }

                if (key == null)

                {

                    throw (new Exception("InstallRoot not Found .."));

                }

                dbPath = key.GetValue("sdkInstallRootv2.0").ToString(); // Print SDK Path

                Console.WriteLine(dbPath); 

            }

            catch (Exception ex)

            {

                Console.WriteLine(ex.Message);

      }

This is the output I got.

SCREEN SHOT 1 : 32 bit Windows 7 & 32 Bit application.

clip_image001

SCREEN SHOT 2 : 64 bit Windows 7 & 64 Bit application.

clip_image002

SCREEN SHOT 3 : 64 bit Windows 7 & 32 Bit application.

clip_image003

 

Note : Although values for 32 bit and 64 applications are different. Application queries same registry key in all three cases (Software\Microsoft\.NETFramework). OS itself mapped the 32 bit and SysWOW64 request to SOFTWARE\Wow6432Node\Microsoft\.NETFramework.

Author : Runeet(MSFT), SQL Developer Engineer, Microsoft 

Reviewed by : Snehadeep(MSFT), SQL Developer Engineer, Microsoft