Introduction
This tip will guide you through Windows registry redirection feature, which might seem quite unintuitive at first acquaintance.
Using the Code
Consider the following situation.
We have code that writes to HKEY_LOCAL_MACHINE
registry on 64-bit OS.
var softwareSubKey = Registry.LocalMachine.OpenSubKey
("Software", RegistryKeyPermissionCheck.ReadWriteSubTree);
softwareSubKey.CreateSubKey("MySoftware");
When successfully executing this code, we somewhat unexpectedly receive no MySoftware folder at \HKEY_LOCAL_MACHINE\SOFTWARE path.
After investigating build tab in project options, we discover the following:
After changing Platform target to x64, we receive an expected result.
Why Does This Happen?
The reason is registry redirector which separates 32 and 64-bit applications providing separate views for them. So in fact when we chose x86 platform target, we just get our key redirected to \HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432Node. Same handles refer to different physical registry location for different target platforms.
As you might expect, registry redirector consistently works with the same physical location. Thus, if we expand our example to deleting created registry folder:
private static void Write()
{
var softwareSubKey = Registry.LocalMachine.OpenSubKey
("Software", RegistryKeyPermissionCheck.ReadWriteSubTree);
softwareSubKey.CreateSubKey("MySoftware");
}
private static void Delete()
{
var softwareSubKey = Registry.LocalMachine.OpenSubKey
("Software", RegistryKeyPermissionCheck.ReadWriteSubTree);
try
{
softwareSubKey.DeleteSubKeyTree("MySoftware", true);
}
catch (ArgumentException)
{
Console.WriteLine("Gotcha!");
Console.ReadKey();
}
}
static void Main(string[] args)
{
Write();
Delete();
}
ArgumentException
won't be fired as we work with the same physical location.
Although if we use 32-bit application and will create manually or by 64-bit application entry in the 64-bit physical location, we'll fail with argument exception as expected.
Avoiding Registry Redirection
You can forcibly write to 32-bit view with 64-bit application and vice versa using RegistryKey.OpenBaseKey
overload which accepts RegistryView
as parameter. For example, the code below writes to \HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432Node regardless of platform target.
var localMachine = RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, RegistryView.Registry32);
var softwareSubKey = localMachine.OpenSubKey("Software", RegistryKeyPermissionCheck.ReadWriteSubTree);
softwareSubKey.CreateSubKey("MySoftware");
On Which Keys Does This Apply?
To know on which keys this applies, use documentation.
Points of Interest
Writing and reading into several registry folders requires elevated permission.
To make the application run under elevated permissions, specify in app.manifest.
<requestedExecutionLevel level="requireAdministrator" uiAccess="false" />
Also to enable write, use the following overload of OpenSubKey
:
Registry.LocalMachine.OpenSubKey("Software", RegistryKeyPermissionCheck.ReadWriteSubTree);
History
- 22.08.2017 - Added "Avoiding Registry Redirection" section
- 04.09.2017 - Fixed small typo