С# считывает неверные данные реестра в 64-разрядной ОС

Я работаю над 64-битной Windows, и мои приложения работают с повышенными привилегиями. У меня проблема со следующим очень простым фрагментом кода:

myKey = Registry.LocalMachine.OpenSubKey(@"SOFTWARE\Microsoft\Windows\CurrentVersion\Run");
    if (myKey != null)
    {
    string[] HKLMvaluenames = myKey.GetValueNames();
    }

Но по какой-то причине массив HKLMvaluenames заполняется значениями из следующего ключа:

HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Run

Есть ли способ решить эту проблему?

Ответ 1

Это по дизайну, 32-разрядные программы имеют другое представление реестра, чем 64-разрядные программы. Они перенаправляются на ключ HKLM\Software\Wow6432Node, когда они пытаются прочитать значение из HKLM\Software hive. Если вы создаете свою С# -программу с помощью Project + Properties, Build, Platform Target = Any CPU, то она будет работать как 64-битная программа и не будет перенаправлена.

32-разрядные программы могут отменить перенаправление, но это нелегко сделать с классом .NET RegistryKey. P/Invoking RegOpenKeyEx с параметром KEY_WOW64_64KEY. Дополнительная информация доступна в этой статье Windows SDK.


EDIT: теперь это также доступно для .NET с помощью специального метода RegistryKey.OpenBaseKey().NET 4. Передайте RegistryView.Registry64, чтобы просмотреть реестр, как это сделал бы 64-разрядный процесс.

Ответ 2

Пока я столкнулся с одной и той же проблемой или тем же фокусом причины этой проблемы, я нашел решение.

Используйте это:

//To set the Base to the right path set RegistryView to DEFAULT, Registry64 or Registry32 regarding the path you need. If you want to go over the x64 root:

RegistryKey rk = RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, RegistryView.Registry64)
        .OpenSubKey(@"SOFTWARE\Microsoft\Windows\CurrentVersion\Run");

Теперь он будет вести себя так, как вы хотите.

Удачи!