Avoid Registry Wow6432Node Redirection
Asked Answered
I

4

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.

Instrumentation answered 4/8, 2012 at 11:56 Comment(1)
possible duplicate of Visual Studio 2010 Setup Project 64 bit create registry key issueVersicular
M
31

You can use RegistryKey.OpenBaseKey to solve this problem:

using var baseReg = RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, RegistryView.Registry64);
using var reg = baseReg.CreateSubKey("Software\\Test");
Marvelous answered 2/4, 2014 at 23:51 Comment(3)
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 solutionDoubletime
Don't forget to dispose baseReg! using(var baseReg = ...) { .. }Wideman
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.Place
H
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.

Hendrix answered 4/8, 2012 at 13:3 Comment(2)
only in the .net 4+ framework, what about .net 3.5 applications?Irremeable
@Irremeable Prior to .net 4 you must call the native API RegOpenKeyEx passing one of the KEY_WOW64_32KEY or KEY_WOW64_64KEY flags as appropriate.Hendrix
A
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

Areopagus answered 4/10, 2013 at 13:6 Comment(1)
The question was how can this be done in C# (programatically), not a registry file or batch file.Sorbose
V
-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");
Viscose answered 16/5, 2017 at 21:38 Comment(4)
This still writes to HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432Node for me :(Ribble
So even with your code, some keys will be redirected even if you specify Registry32, such as SOFTWARE Refer to MSDN article on which keys are redirected msdn.microsoft.com/en-gb/library/aa384253%28v=VS.85%29.aspxRibble
Hmm. There might be something setup incorrectly in your project, then. In your app.manifest, what do you have requestedExecutionLevel set to?Viscose
<requestedExecutionLevel level="requireAdministrator" uiAccess="false" />Ribble

© 2022 - 2024 — McMap. All rights reserved.