C # Чтение реестра: ProductID возвращает null в целевом приложении x86. «Любой процессор» работает нормально

#c# #visual-studio-2010 #registry #32bit-64bit

#c# #visual-studio-2010 #реестр #32-64-битный

Вопрос:

Недавно я перешел на 64-разрядную машину W7 с VS 2010. Мой проект настроен на запуск Any CPU . Когда я изменил это, чтобы оно было нацелено на x86 , я заметил, что некоторые из моих вызовов реестра больше не работают.

Я пытаюсь прочитать ProductID поле следующим образом:

 RegistryKey windowsNTKey = Registry.LocalMachine.OpenSubKey(@"SoftwareMicrosoftWindows NTCurrentVersion");
object productID = windowsNTKey.GetValue("ProductId");
  

productID всегда null при запуске в режиме x86, при запуске на «любом процессоре» он работает правильно. Что здесь происходит?

Комментарии:

1. Это — чтение из другой области реестра. Однако я не знаю, какой лучший способ работать с этим.

2. @Rup — Как мне это обойти?

Ответ №1:

Некоторые разделы реестра перенаправляются WOW64. Дополнительная информация по этому вопросу доступна в MSDN http://msdn.microsoft.com/en-us/library/aa384232 (v = против 85).aspx

Если вы действительно хотите всегда обращаться к узлу x64 (.Net4) :

   RegistryKey localMachine = RegistryKey.OpenBaseKey(Microsoft.Win32.RegistryHive.LocalMachine, RegistryView.Registry64);
  RegistryKey windowsNTKey = localMachine.OpenSubKey(@"SoftwareMicrosoftWindows NTCurrentVersion");
  object productID = windowsNTKey.GetValue("ProductId");
  

Комментарии:

1. ` RegistryKey. OpenBaseKey` для меня не существует… У меня есть только RegistryKey.OpenRemoteBaseKey ? Я using Microsoft.Win32; так и не могу понять, почему?

2. @Chris единственное различие, которое я вижу между двумя методами доступа, заключается в том, что OpenbaseKey не ComVisible

3. Использование OpenRemoteBaseKey не позволяет мне передавать RegistryView перечисление в качестве аргумента, нужно ли ссылаться на специальную сборку?

4. Ах… Я ориентируюсь на 3.5, эти функции доступны только в .NET 4

Ответ №2:

Этот код получит идентификатор для всех видов архитектур ОС и программных архитектур. Можно было бы написать короче, но мне нравится удобочитаемость

     static string GetProductId()
    {
        RegistryKey localMachine = null;
        if (Environment.Is64BitOperatingSystem)
        {
            localMachine = RegistryKey.OpenBaseKey(Microsoft.Win32.RegistryHive.LocalMachine, RegistryView.Registry64);
        }
        else
        {
            localMachine = RegistryKey.OpenBaseKey(Microsoft.Win32.RegistryHive.LocalMachine, RegistryView.Registry32);
        }
        RegistryKey windowsNTKey = localMachine.OpenSubKey(@"SoftwareMicrosoftWindows NTCurrentVersion");
        return windowsNTKey.GetValue("ProductId").ToString();
    }
  

Комментарии:

1. «Если вы запрашиваете 64-разрядное представление в 32-разрядной операционной системе, возвращаемые ключи будут в 32-разрядном представлении». msdn.microsoft.com/fr-fr/library /…

Ответ №3:

В win64 некоторые разделы реестра 32-разрядного приложения хранятся в SoftwareWow6432Node подразделе.

Если вы хотите переключиться на 64-разрядный ключ, вы можете использовать RegistryView enum в качестве параметра RegistryKey.OpenBaseKey

Лично для того, чтобы код всегда работал в главном разделе реестра (не WoW6432), я использую такую конструкцию:

RegistryKey.OpenBaseKey(RegistryHive.CurrentUser, Environment.Is64BitOperatingSystem ? RegistryView.Registry64 : RegistryView.Registry32)