读取registry和Wow6432Node键
我有一些代码读取registry,并在HKEY_LOCAL_MACHINE\Software\App\
查找值,但在64位版本的Windows上运行时,该值在HKEY_LOCAL_MACHINE\Software\Wow6432Node\App\
。
我应该如何最好的方法呢? 我是否需要一个64位安装程序,或者我应该重写我的代码来检测这两个地方?
如果您将C#程序标记为x86(而不是任何CPU),则会将HKEY_LOCAL_MACHINE\Software\Wow6432Node\App
标识为HKEY_LOCAL_MACHINE\Software\App\
。
如果安装了64位.NET,任何CPU的.NET程序将以64位进程运行。 32位registry位于64位程序的Wow6432Node
下。
在x64机器上,下面是如何访问registry的32位视图的示例:
using (var view32 = RegistryKey.OpenBaseKey(RegistryHive.CurrentUser, RegistryView.Registry32)) { using (var clsid32 = view32.OpenSubKey(@"Software\Classes\CLSID\", false)) { // actually accessing Wow6432Node } }
…相比…
using (var view64 = RegistryKey.OpenBaseKey(RegistryHive.CurrentUser, RegistryView.Registry64)) { using (var clsid64 = view64.OpenSubKey(@"Software\Classes\CLSID\", true)) { .... } }
+1给Wally的答案,但他的解决scheme适用于.NET 4.0及更高版本。
我发现了另一个解决scheme,这也适用于.NET 2.0
#region RegHelper 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 } static class RegHive { public static UIntPtr HKEY_LOCAL_MACHINE = new UIntPtr(0x80000002u); public static UIntPtr HKEY_CURRENT_USER = new UIntPtr(0x80000001u); } static class RegistryWOW6432 { [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); 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
用法:
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");
这是一个全面的解决scheme,将涵盖安装在本地机器或用户帐户上的x32 / x64系统和捕获应用程序。
public class InstalledProgramInfo { public string name; public string path; } public static InstalledProgramInfo FindInstalledApp(string findname, bool dump = false) { if (String.IsNullOrEmpty(findname)) return null; string uninstallKey = @"SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall"; RegistryHive[] keys = new RegistryHive[] { RegistryHive.CurrentUser, RegistryHive.LocalMachine }; RegistryView[] views = new RegistryView[] { RegistryView.Registry32, RegistryView.Registry64 }; foreach (var hive in keys) { foreach (var view in views) { RegistryKey rk = null, basekey = null; try { basekey = RegistryKey.OpenBaseKey(hive, view); rk = basekey.OpenSubKey(uninstallKey); } catch (Exception ex) { continue; } if (basekey == null || rk == null) continue; if (rk == null) { if (dump) Console.WriteLine("ERROR: failed to open subkey '{0}'", uninstallKey); return null; } if (dump) Console.WriteLine("Reading registry at {0}", rk.ToString()); foreach (string skName in rk.GetSubKeyNames()) { try { RegistryKey sk = rk.OpenSubKey(skName); if (sk == null) continue; object skname = sk.GetValue("DisplayName"); object skpath = sk.GetValue("InstallLocation"); if (skpath == null) { skpath = sk.GetValue("UninstallString"); if (skpath == null) continue; FileInfo fi = new FileInfo(skpath.ToString()); skpath = fi.Directory.FullName; } if (skname == null || skpath == null) continue; string thisname = skname.ToString(); string thispath = skpath.ToString(); if (dump) Console.WriteLine("{0}: {1}", thisname, thispath); if (!thisname.Equals(findname, StringComparison.CurrentCultureIgnoreCase)) continue; InstalledProgramInfo inf = new InstalledProgramInfo(); inf.name = thisname; inf.path = thispath; return inf; } catch (Exception ex) { // todo } } } // view } // hive return null; }