How to read the 64 bit registry from a 32 bit application or vice versa
I found out that I needed to read the 64 bit registry from a 32 bit app today.
Why you might ask?
Well, I need to get the RegisteredOrganization value from HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion and unfortunately Microsoft has a bug where the WOW6432 version of this key always says Microsoft, so a 32 bit application would always return Microsoft as the RegisteredOrganization, regardless of what the user entered when they installed the OS. This is hardly desired.
Note: This is also why all Visual Studio projects created in Windows 7 64 bit have Microsoft in the project’s Assembly Information. Change the WOW6432 version of the RegisteredOrganization and you fix this Visual Studio issue.
Well, turns out C# doesn’t have functionality until .NET 4, so prior to .NET 4, to choose the 64 bit hive when running a 32 bit app, so we have to do use a DLLImport and use RegOpenKeyEx, RegCloseKey, and RegQueryValueEx.
I don’t have this well commented, and it is not very newbie proof, but here are three different ways to do this. Hopefully you can understand one or more of these.
Example 1 – .NET 4 Example
Here is how to do this in .NET 4.
using Microsoft.Win32; namespace Read64bitRegistryFrom32bitApp { class Program { static void Main(string[] args) { string value64 = string.Empty; string value32 = string.Empty; RegistryKey localKey = RegistryKey.OpenBaseKey(Microsoft.Win32.RegistryHive.LocalMachine, RegistryView.Registry64); localKey = localKey.OpenSubKey(@"SOFTWARE\Microsoft\Windows NT\CurrentVersion"); if (localKey != null) { value64 = localKey.GetValue("RegisteredOrganization").ToString(); } RegistryKey localKey32 = RegistryKey.OpenBaseKey(Microsoft.Win32.RegistryHive.LocalMachine, RegistryView.Registry32); localKey32 = localKey32.OpenSubKey(@"SOFTWARE\Microsoft\Windows NT\CurrentVersion"); if (localKey32 != null) { value32 = localKey32.GetValue("RegisteredOrganization").ToString(); } } } }
.NET 3.5 SP1 and Prior
We have to do use a DLLImport and use RegOpenKeyEx, RegCloseKey, and RegQueryValueEx. Here are some examples.
Example 1 – A console application to read the 64 bit registry from a 32 bit application or vice versa
using System; using System.Runtime.InteropServices; using System.Text; namespace Read64bitRegistryFrom32bitApp { class Program { static void Main(string[] args) { string value64 = GetRegKey64(RegHive.HKEY_LOCAL_MACHINE, @"SOFTWARE\Microsoft\Windows NT\CurrentVersion", "RegisteredOrganization"); Console.WriteLine(value64); string value32 = GetRegKey32(RegHive.HKEY_LOCAL_MACHINE, @"SOFTWARE\Microsoft\Windows NT\CurrentVersion", "RegisteredOrganization"); Console.WriteLine(value32); } public enum RegSAM { QueryValue = 0x0001, SetValue = 0x0002, CreateSubKey = 0x0004, EnumerateSubKeys = 0x0008, Notify = 0x0010, CreateLink = 0x0020, WOW64_32Key = 0x0200, WOW64_64Key = 0x0100, WOW64_Res = 0x0300, Read = 0x00020019, Write = 0x00020006, Execute = 0x00020019, AllAccess = 0x000f003f } public static UIntPtr HKEY_LOCAL_MACHINE = new UIntPtr(0x80000002u); public static UIntPtr HKEY_CURRENT_USER = new UIntPtr(0x80000001u); #region Member Variables #region Read 64bit Reg from 32bit app [DllImport("Advapi32.dll")] static extern uint RegOpenKeyEx( UIntPtr hKey, string lpSubKey, uint ulOptions, int samDesired, out int phkResult); [DllImport("Advapi32.dll")] static extern uint RegCloseKey(int hKey); [DllImport("advapi32.dll", EntryPoint = "RegQueryValueEx")] public static extern int RegQueryValueEx( int hKey, string lpValueName, int lpReserved, ref uint lpType, System.Text.StringBuilder lpData, ref uint lpcbData); #endregion #endregion #region Functions static public string GetRegKey64(UIntPtr inHive, String inKeyName, String inPropertyName) { return GetRegKey64(inHive, inKeyName, RegSAM.WOW64_64Key, inPropertyName); } static public string GetRegKey32(UIntPtr inHive, String inKeyName, String inPropertyName) { return GetRegKey64(inHive, inKeyName, RegSAM.WOW64_32Key, inPropertyName); } static public string GetRegKey64(UIntPtr inHive, String inKeyName, RegSAM in32or64key, String inPropertyName) { //UIntPtr HKEY_LOCAL_MACHINE = (UIntPtr)0x80000002; int hkey = 0; try { uint lResult = RegOpenKeyEx(RegHive.HKEY_LOCAL_MACHINE, inKeyName, 0, (int)RegSAM.QueryValue | (int)in32or64key, out hkey); if (0 != lResult) return null; uint lpType = 0; uint lpcbData = 1024; StringBuilder AgeBuffer = new StringBuilder(1024); RegQueryValueEx(hkey, inPropertyName, 0, ref lpType, AgeBuffer, ref lpcbData); string Age = AgeBuffer.ToString(); return Age; } finally { if (0 != hkey) RegCloseKey(hkey); } } #endregion } }
Example 2 – A static class to read the 64 bit registry from a 32 bit application or vice versa
using System; using System.Runtime.InteropServices; using System.Text; namespace Read64bitRegistryFrom32bitApp { public enum RegSAM { QueryValue = 0x0001, SetValue = 0x0002, CreateSubKey = 0x0004, EnumerateSubKeys = 0x0008, Notify = 0x0010, CreateLink = 0x0020, WOW64_32Key = 0x0200, WOW64_64Key = 0x0100, WOW64_Res = 0x0300, Read = 0x00020019, Write = 0x00020006, Execute = 0x00020019, AllAccess = 0x000f003f } public static class RegHive { public static UIntPtr HKEY_LOCAL_MACHINE = new UIntPtr(0x80000002u); public static UIntPtr HKEY_CURRENT_USER = new UIntPtr(0x80000001u); } public static class RegistryWOW6432 { #region Member Variables #region Read 64bit Reg from 32bit app [DllImport("Advapi32.dll")] static extern uint RegOpenKeyEx( UIntPtr hKey, string lpSubKey, uint ulOptions, int samDesired, out int phkResult); [DllImport("Advapi32.dll")] static extern uint RegCloseKey(int hKey); [DllImport("advapi32.dll", EntryPoint = "RegQueryValueEx")] public static extern int RegQueryValueEx( int hKey, string lpValueName, int lpReserved, ref uint lpType, System.Text.StringBuilder lpData, ref uint lpcbData); #endregion #endregion #region Functions static public string GetRegKey64(UIntPtr inHive, String inKeyName, String inPropertyName) { return GetRegKey64(inHive, inKeyName, RegSAM.WOW64_64Key, inPropertyName); } static public string GetRegKey32(UIntPtr inHive, String inKeyName, String inPropertyName) { return GetRegKey64(inHive, inKeyName, RegSAM.WOW64_32Key, inPropertyName); } static public string GetRegKey64(UIntPtr inHive, String inKeyName, RegSAM in32or64key, String inPropertyName) { //UIntPtr HKEY_LOCAL_MACHINE = (UIntPtr)0x80000002; int hkey = 0; try { uint lResult = RegOpenKeyEx(RegHive.HKEY_LOCAL_MACHINE, inKeyName, 0, (int)RegSAM.QueryValue | (int)in32or64key, out hkey); if (0 != lResult) return null; uint lpType = 0; uint lpcbData = 1024; StringBuilder AgeBuffer = new StringBuilder(1024); RegQueryValueEx(hkey, inPropertyName, 0, ref lpType, AgeBuffer, ref lpcbData); string Age = AgeBuffer.ToString(); return Age; } finally { if (0 != hkey) RegCloseKey(hkey); } } #endregion #region Enums #endregion } }
using System; using System.Runtime.InteropServices; using System.Text; namespace Read64bitRegistryFrom32bitApp { class Program { static void Main(string[] args) { string value64 = RegistryWOW6432.GetRegKey64(RegHive.HKEY_LOCAL_MACHINE, @"SOFTWARE\Microsoft\Windows NT\CurrentVersion", "RegisteredOrganization"); string value32 = RegistryWOW6432.GetRegKey32(RegHive.HKEY_LOCAL_MACHINE, @"SOFTWARE\Microsoft\Windows NT\CurrentVersion", "RegisteredOrganization"); } } }
Example 3 – Adding extension methods to the managed RegistryKey object that read the 64 bit registry from a 32 bit application or vice versa
using System; using System.Runtime.InteropServices; using System.Text; using Microsoft.Win32; namespace Read64bitRegistryFrom32bitApp { /// <summary> /// An extension class to allow a registry key to allow it to get the /// registry in the 32 bit (Wow6432Node) or 64 bit regular registry key /// </summary> public static class RegistryWOW6432 { #region Member Variables #region Read 64bit Reg from 32bit app public static UIntPtr HKEY_LOCAL_MACHINE = new UIntPtr(0x80000002u); public static UIntPtr HKEY_CURRENT_USER = new UIntPtr(0x80000001u); [DllImport("Advapi32.dll")] static extern uint RegOpenKeyEx( UIntPtr hKey, string lpSubKey, uint ulOptions, int samDesired, out int phkResult); [DllImport("Advapi32.dll")] static extern uint RegCloseKey(int hKey); [DllImport("advapi32.dll", EntryPoint = "RegQueryValueEx")] public static extern int RegQueryValueEx( int hKey, string lpValueName, int lpReserved, ref RegistryValueKind lpType, StringBuilder lpData, ref uint lpcbData); [DllImport("advapi32.dll", CharSet = CharSet.Unicode, EntryPoint = "RegQueryValueEx")] private static extern int RegQueryValueEx( int hKey, string lpValueName, int lpReserved, ref RegistryValueKind lpType, [Out] byte[] lpData, ref uint lpcbData); #endregion #endregion #region Functions public static string GetRegKey64(this RegistryKey inKey, String inPropertyName) { string strKey = inKey.ToString(); string regHive = strKey.Split('\\')[0]; string regPath = strKey.Substring(strKey.IndexOf('\\') + 1); return GetRegKey64(GetRegHiveFromString(regHive), regPath, RegSAM.WOW64_64Key, inPropertyName); } public static string GetRegKey32(this RegistryKey inKey, String inPropertyName) { string strKey = inKey.ToString(); string regHive = strKey.Split('\\')[0]; string regPath = strKey.Substring(strKey.IndexOf('\\') + 1); return GetRegKey64(GetRegHiveFromString(regHive), regPath, RegSAM.WOW64_32Key, inPropertyName); } public static byte[] GetRegKey64AsByteArray(this RegistryKey inKey, String inPropertyName) { string strKey = inKey.ToString(); string regHive = strKey.Split('\\')[0]; string regPath = strKey.Substring(strKey.IndexOf('\\') + 1); return GetRegKey64AsByteArray(GetRegHiveFromString(regHive), regPath, RegSAM.WOW64_64Key, inPropertyName); } public static byte[] GetRegKey32AsByteArray(this RegistryKey inKey, String inPropertyName) { string strKey = inKey.ToString(); string regHive = strKey.Split('\\')[0]; string regPath = strKey.Substring(strKey.IndexOf('\\') + 1); return GetRegKey64AsByteArray(GetRegHiveFromString(regHive), regPath, RegSAM.WOW64_32Key, inPropertyName); } private static UIntPtr GetRegHiveFromString(string inString) { if (inString == "HKEY_LOCAL_MACHINE") return HKEY_LOCAL_MACHINE; if (inString == "HKEY_CURRENT_USER") return HKEY_CURRENT_USER; return UIntPtr.Zero; } static public string GetRegKey64(UIntPtr inHive, String inKeyName, RegSAM in32or64key, String inPropertyName) { //UIntPtr HKEY_LOCAL_MACHINE = (UIntPtr)0x80000002; int hkey = 0; try { uint lResult = RegOpenKeyEx(inHive, inKeyName, 0, (int)RegSAM.QueryValue | (int)in32or64key, out hkey); if (0 != lResult) return null; RegistryValueKind lpType = 0; uint lpcbData = 1024; StringBuilder strBuffer = new StringBuilder(1024); RegQueryValueEx(hkey, inPropertyName, 0, ref lpType, strBuffer, ref lpcbData); string value = strBuffer.ToString(); return value; } finally { if (0 != hkey) RegCloseKey(hkey); } } static public byte[] GetRegKey64AsByteArray(UIntPtr inHive, String inKeyName, RegSAM in32or64key, String inPropertyName) { int hkey = 0; try { uint lResult = RegOpenKeyEx(inHive, inKeyName, 0, (int)RegSAM.QueryValue | (int)in32or64key, out hkey); if (0 != lResult) return null; RegistryValueKind lpType = 0; uint lpcbData = 2048; // Just make a big buffer the first time byte[] byteBuffer = new byte[1000]; // The first time, get the real size RegQueryValueEx(hkey, inPropertyName, 0, ref lpType, byteBuffer, ref lpcbData); // Now create a correctly sized buffer byteBuffer = new byte[lpcbData]; // now get the real value RegQueryValueEx(hkey, inPropertyName, 0, ref lpType, byteBuffer, ref lpcbData); return byteBuffer; } finally { if (0 != hkey) RegCloseKey(hkey); } } #endregion #region Enums public enum RegSAM { QueryValue = 0x0001, SetValue = 0x0002, CreateSubKey = 0x0004, EnumerateSubKeys = 0x0008, Notify = 0x0010, CreateLink = 0x0020, WOW64_32Key = 0x0200, WOW64_64Key = 0x0100, WOW64_Res = 0x0300, Read = 0x00020019, Write = 0x00020006, Execute = 0x00020019, AllAccess = 0x000f003f } #endregion } }
using Microsoft.Win32; namespace Read64bitRegistryFrom32bitApp { class Program { static void Main(string[] args) { string value64 = string.Empty; string value32 = string.Empty; byte[] byteValue64 = new byte[1024]; byte[] byteValue32 = new byte[1024]; RegistryKey localKey = Registry.LocalMachine; localKey = localKey.OpenSubKey(@"SOFTWARE\Microsoft\Windows NT\CurrentVersion"); if (localKey != null) { value32 = localKey.GetRegKey32("RegisteredOrganization"); value64 = localKey.GetRegKey64("RegisteredOrganization"); // byteValue32 = localKey.GetRegKey32AsByteArray("DigitalProductId"); // Key doesn't exist by default in 32 bit byteValue64 = localKey.GetRegKey64AsByteArray("DigitalProductId"); } } } }
- RegOpenKeyEx Function – http://msdn.microsoft.com/en-us/library/ms724897%28v=VS.85%29.aspx
- RegQueryValueEx Function – http://msdn.microsoft.com/en-us/library/ms724911%28VS.85%29.aspx
- http://www.pinvoke.net/default.aspx/advapi32/RegQueryValueEx.html
- http://www.pinvoke.net/default.aspx/advapi32/RegOpenKeyEx.html
- http://www.pinvoke.net/default.aspx/advapi32/RegCreateKeyEx.html
- http://www.pinvoke.net/default.aspx/advapi32/RegCloseKey.html
- http://stackoverflow.com/questions/1470770/accessing-registry-using-net
- http://connect.microsoft.com/VisualStudio/feedback/details/400597/registeredorganization-reg-key-on-x64-vista-7
Copyright ® Rhyous.com – Linking to this post is allowed without permission and as many as ten lines of this page can be used along with this link. Any other use of this page is allowed only by permission of Rhyous.com.