31

I'm trying to insert some simple registry keys using Microsoft.Win32.RegistryKey in c# but the path automatically changes from:

HKEY_LOCAL_MACHINE\SOFTWARE\Test

to

HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Test

I tried google but I only get some vague and confusing results. Has anyone dealt with this issue before? Some example code would be much appereciated.

  • 1
    possible duplicate of [Visual Studio 2010 Setup Project 64 bit create registry key issue](http://stackoverflow.com/questions/7384270/visual-studio-2010-setup-project-64-bit-create-registry-key-issue) – Hans Passant Aug 04 '12 at 15:15

4 Answers4

31

You can use RegistryKey.OpenBaseKey to solve this problem:

var baseReg = RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, RegistryView.Registry64);
var reg = baseReg.CreateSubKey("Software\\Test");
Hui
  • 426
  • 4
  • 4
  • I was searching for an example of how to use RegistryView.Registry64 and by accident found it here. None of the M$ docs have an example, they just say use it. My any CPU app was reading the wow6432uninstall when I told it to read the regular uninstall. This is the solution – sdjuan Oct 13 '16 at 02:46
  • 4
    Don't forget to dispose baseReg! using(var baseReg = ...) { .. } – Vladimir Arustamian Sep 01 '17 at 09:57
  • Thank You @Hui. Tricky! If one wants to do it correctly, the UAC elevation level has to be set correctly and the normal `Registry.LocalMaching.OpenKey` only leads to a key in the `WOW6432Node`-Path. `RegistryGetValue` fails completely and only virtualises. – DrMarbuse Jan 27 '20 at 09:35
9

Under WOW64, certain registry keys are redirected (SOFTWARE). When a 32-bit or 64-bit application makes a registry call for a redirected key, the registry redirector intercepts the call and maps it to the key's corresponding physical registry location. For more information, see Registry Redirector.

You can use the RegistryView Enumeration on RegistryKey.OpenBaseKey Method to open the 32-bit view explicitly and access HKLM\Software\ directly.

Jacob Seleznev
  • 8,013
  • 3
  • 24
  • 34
  • only in the .net 4+ framework, what about .net 3.5 applications? – Kevin Mar 04 '15 at 17:37
  • 4
    @Kevin Prior to .net 4 you must call the native API [RegOpenKeyEx](https://msdn.microsoft.com/en-us/library/ms724897(VS.85).aspx) passing one of the [KEY_WOW64_32KEY or KEY_WOW64_64KEY](https://msdn.microsoft.com/en-us/library/windows/desktop/aa384129(v=vs.85).aspx) flags as appropriate. – Jacob Seleznev Mar 05 '15 at 06:59
9

I don't know how to solve it using a .reg file. But only in a BAT file, as follow:

You must add /reg:64 at the end of the command line. ex:

REG ADD "HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Authentication\LogonUI\Background" /v "OEMBackground" /t REG_DWORD /d 0x00000001 /f /reg:64

Source: Wow6432Node and how to Deploy Registry settings to 64 bit systems via Sccm

stema
  • 90,351
  • 20
  • 107
  • 135
Pedro77
  • 5,176
  • 7
  • 61
  • 91
-1

Here is the working code I have developed to both read and write ONLY the 32-bit registry. It works in both 32-bit and 64-bit applications. The 'read' call updates the registry if the value is not set, but it is very obvious how to remove that. It requires .Net 4.0, and uses the OpenBaseKey/OpenSubKey methods.

I currently use it to allow a 64-bit background service and a 32-bit tray application to access the same registry keys seamlessly.

using Microsoft.Win32;

namespace SimpleSettings
{
public class Settings
{
    private static string RegistrySubKey = @"SOFTWARE\BlahCompany\BlahApp";

    public static void write(string setting, string value)
    {
        using (RegistryKey registryView = RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, RegistryView.Registry32))
        using (RegistryKey registryCreate = registryView.CreateSubKey(RegistrySubKey))
        using (RegistryKey registryKey = registryView.OpenSubKey(RegistrySubKey, true))
        {
            registryKey.SetValue(setting, value, RegistryValueKind.String);
        }        
    }
    public static string read(string setting, string def)
    {
        string output = string.Empty;
        using (RegistryKey registryView = RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, RegistryView.Registry32))
        using (RegistryKey registryCreate = registryView.CreateSubKey(RegistrySubKey))
        using (RegistryKey registryKey = registryView.OpenSubKey(RegistrySubKey, false))
        {
            // Read the registry, but if it is blank, update the registry and return the default.
            output = (string)registryKey.GetValue(setting, string.Empty);
            if (string.IsNullOrWhiteSpace(output))
            {
                output = def;
                write(setting, def);
            }
        }
        return output;
    }
}
}

Usage: Put this in it's own class file (.cs) and call it as such:

using SimpleSettings;
string mysetting = Settings.read("SETTINGNAME","DEFAULTVALUE");
Miles Prower
  • 105
  • 9