Чтение реестра и ключа Wow6432Node - PullRequest
46 голосов
/ 11 января 2010

У меня есть некоторый код, который читает реестр и ищет значение в HKEY_LOCAL_MACHINE\Software\App\, но при работе в 64-разрядных версиях Windows это значение меньше HKEY_LOCAL_MACHINE\Software\Wow6432Node\App\.

Как мне лучше всего подойти к этому? Нужен ли мне 64-битный установщик или я должен переписать свой код, чтобы обнаружить оба места?

Ответы [ 4 ]

70 голосов
/ 12 сентября 2013

На компьютере с архитектурой x64 приведен пример доступа к 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))
  {
    ....
  }
}
47 голосов
/ 11 января 2010

Если вы пометите свою программу на C # как x86 (а не Any CPU), то она увидит HKEY_LOCAL_MACHINE\Software\Wow6432Node\App как HKEY_LOCAL_MACHINE\Software\App\.

Программа .NET для любого процессора будет работать как 64-битный процесс, если установлен 64-битный .NET. 32-разрядный реестр находится под Wow6432Node для 64-разрядных программ.

7 голосов
/ 26 августа 2014

+ 1 к ответу Уолли, но его решение работает для .NET 4.0 и выше.

Я нашел другое решение, которое также работает для .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");
4 голосов
/ 08 мая 2015

Это комплексное решение, которое будет охватывать системы 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;
    }
...