SetValue 64bit machine registry - c#

I want to set a value for 'NoModify' in below registry path.
"HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\XXXX"
I am using below code and it works only for X86 machines. Can you see any reason why this is not working for x64 machines?
// This value is correct
RegistryView registryView = releaseFlags.Contains("PLATFORM_X86") ? RegistryView.Registry64 : RegistryView.Registry32;
using (RegistryKey hkeyLocalMachine = RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, registryView))
{
RegistryKey noModifyKey = hkeyLocalMachine.OpenSubKey(#"SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\{xxxx}", true); //SL: Key Name
if (noModifyKey != null)
{
noModifyKey.SetValue("NoModify", 0);
noModifyKey.Flush();
}
}

When you are on a 64 bit machine and your app is 32 bit - it should store these settings in the HKLM\Software\WOW6432Node instead of the HKLM\Software\ node.

You should open base key in this way.
It works for me.
var rk = Microsoft.Win32.RegistryKey.OpenBaseKey(Microsoft.Win32.RegistryHive.LocalMachine, RegistryView.Registry32);
if (Environment.Is64BitOperatingSystem) {
rk = Microsoft.Win32.RegistryKey.OpenBaseKey(Microsoft.Win32.RegistryHive.LocalMachine, RegistryView.Registry64);
var val = rk.OpenSubKey("SOFTWARE\\Pourab\\sanjande", true);
val.SetValue("test", "testvalue");
}

As far as you compiles your .NET program as x86 not AnyCPU, you will be using the "correct" registry keys meant for x86 in any circumstances because it will be running as x86.
If you compile it as x64 or AnyCPU, it could be quite tricky because it will probably run as x64 on an x64 machine and uses the "wrong" registry where HKLM\SOFTWARE for x86 programs is actually HKLM\SOFTWARE\WOW6432Node.

It's my mistake in the code.
RegistryView registryView = releaseFlags.Contains("PLATFORM_X86") ? RegistryView.Registry64 : RegistryView.Registry32;
Should be as follows:
RegistryView registryView = releaseFlags.Contains("PLATFORM_X86") ? RegistryView.Registry32 : RegistryView.Registry64;

Related

Registry key null on 64 bit machine

This seemed quite a simple task. First I write registry key
string strHiveName = #"Software\AAAA";
RegistryKey key1_LM;
key1_LM = Registry.LocalMachine.CreateSubKey(strHiveName);
key1_LM.SetValue("Val1", strHiveName);
key1_LM.Close();
and I find it here
HKEY_USERS\S-1-5-21-2753797750-1692135373-930909737-45181\Software\AAAA
when I want to read it with:
RegistryKey root_LM32 = RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, RegistryView.Default);
RegistryKey foundProgramKey_LM32 = root_LM32.OpenSubKey(#"SOFTWARE\AAAA");
RegistryKey root_LM64 = RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, RegistryView.Registry64);
RegistryKey foundProgramKey_LM64 = root_LM64.OpenSubKey(#"SOFTWARE\AAAA");
this since I want to make it run on both 32 and 64 bit machines so I expect that at least of the two registry keys are not null but that's not the case.
I have searched this and this but none seems to help.

C# Cant Access Some Registry Values

I need to read default value of HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Classes\CLSID{CF2CF428-325B-48d3-8CA8-7633E36E5A32}\InprocServer32
In my Project options "Prefer 32-Bit" is unchecked and Platform target is Any CPU, i'm running on Windows-7 64 Bit operating system.
I tried everything and read A LOT of topics about this issue but i can't still read this value.
Please, can you write the actual code ?
I Tried,
RegistryKey LocalMachine32 = RegistryKey.OpenBaseKey(Microsoft.Win32.RegistryHive.LocalMachine, RegistryView.Registry32);
RegistryKey location = LocalMachine32.OpenSubKey(#"Software\Wow6432Node\Classes\CLSID\{CF2CF428-325B-48d3-8CA8-7633E36E5A32}\InprocServer32", true);
String myValue = location.GetValue("").ToString();
.
RegistryKey LocalMachine64 = RegistryKey.OpenBaseKey(Microsoft.Win32.RegistryHive.LocalMachine, RegistryView.Registry64);
RegistryKey location = LocalMachine64.OpenSubKey(#"Software\Wow6432Node\Classes\CLSID\{CF2CF428-325B-48d3-8CA8-7633E36E5A32}\InprocServer32", true);
String myValue = location.GetValue("").ToString();
.
RegistryKey LocalMachine64 = RegistryKey.OpenBaseKey(Microsoft.Win32.RegistryHive.LocalMachine, RegistryView.Registry64);
RegistryKey location = LocalMachine64.OpenSubKey(#"Software\Classes\CLSID\{CF2CF428-325B-48d3-8CA8-7633E36E5A32}\InprocServer32", true);
String myValue = location.GetValue("").ToString();
.
RegistryKey LocalMachine32 = RegistryKey.OpenBaseKey(Microsoft.Win32.RegistryHive.LocalMachine, RegistryView.Registry32);
RegistryKey location = LocalMachine32.OpenSubKey(#"Software\Classes\CLSID\{CF2CF428-325B-48d3-8CA8-7633E36E5A32}\InprocServer32", true);
String myValue = location.GetValue("").ToString();
But no luck :(
As far as I'm aware you cannot do this with .NET Framework calls; in the past I've used P/Invoke calls to advapi32.dll's RegOpenKeyEx, RegQueryValueEx, and RegQueryValueEx methods to read from a specific bitness registry.
Here is an article with an example of doing this:
http://blogs.msdn.com/b/cumgranosalis/archive/2005/12/19/win64registrypart2.aspx
Edit:
The reason it doesn't work in Windows 7 (along with other potentially helpful resources) is discussed here:
How to open a WOW64 registry key from a 64-bit .NET application

Unable to return a WOW6432 version of a key from 32bit application

I'm trying to read a registry key from my application. It is a 32-bit process and is running on a 64-bit system(Win7 64-bit). This is my code:
string value64 = string.Empty;
RegistryKey localKeyRegistryKey.OpenBaseKey(Microsoft.Win32.RegistryHive.LocalMachine, RegistryView.Registry64);
localKey = localKey.OpenSubKey(#"SOFTWARE\Microsoft\Windows NT\CurrentVersion");
if (localKey != null)
{
value64 = localKey.GetValue("RegisteredOrganization").ToString();
MessageBox.Show(value64, "value64");
}
On my system the value under this key(SOFTWARE\Microsoft\Windows NT\CurrentVersion) is empty, and the value under this(SOFTWARE\WOW6432Node\Microsoft\Windows NT\CurrentVersion) is "Microsoft". But the value64 in the message box is empty! Shouldn't it be "Microsoft"?
You are specifying RegistryView.Registry64 so it will be retrieving the value from SOFTWARE\Microsoft\Windows NT\CurrentVersion
If you specify RegistryView.Registry32 it will retrieve it from SOFTWARE\WOW6432Node\Microsoft\Windows NT\CurrentVersion instead (that is, on a 64-bit system; on a 32-bit system the WOW6432Node doesn't exist so it will just use the normal hive instead).
I think that if you specify RegistryView.Default it will select the hive according to the bitness of the calling process.

Registry keys handling 64 bit OS

I am using registry keys to access the path of an XML file from installed folder of my machine.
My machine has 32 bit OS. So I am using
using (RegistryKey pRegKey = Registry.LocalMachine.OpenSubKey(#"SOFTWARE\Wow6432Node\Folder\subfolder\key"))
{
if (pRegKey == null)
{
return;
}
else
// get path
But when I run it in 64 bit machine it is showing error, since I have not handled the exception case for 64 bit OS.
How can I handle it??
If your app is 32-bit and you want to install it both on 32-bit and 64-bit OS, use this:
string regPath = string.Format(#"SOFTWARE\{0}AppName\Folder\subfolder\key",
Environment.Is64BitProcess ? #"Wow6432Node\" : string.Empty());
using (RegistryKey pRegKey = Registry.LocalMachine.OpenSubKey(regPath))
{
.....

Avoid Registry Wow6432Node Redirection

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.
You can use RegistryKey.OpenBaseKey to solve this problem:
var baseReg = RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, RegistryView.Registry64);
var reg = baseReg.CreateSubKey("Software\\Test");
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.
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
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");

Categories

Resources