Reading the Registry and Wow6432Node Key

Reading the registry and Wow6432Node key

If you mark you C# program as x86 (and not Any CPU) then it will see HKEY_LOCAL_MACHINE\Software\Wow6432Node\App as HKEY_LOCAL_MACHINE\Software\App\.

A .NET program for Any CPU will run as a 64-bit process if 64-bit .NET is installed. The 32-bit registry is under the Wow6432Node for 64-bit programs.

Reading registry in both 64 and 32 bit windows

Windows 64 bit system divide registry into two part. One for 32 and another for 64 bit system.
I believe you should update your call to following:

RegOpenKeyEx(HKEY_LOCAL_MACHINE, Path, 0, KEY_ALL_ACCESS | KEY_WOW64_32KEY, &hKey)

Reading registry in both 64 and 32 bit windows

Windows 64 bit system divide registry into two part. One for 32 and another for 64 bit system.
I believe you should update your call to following:

RegOpenKeyEx(HKEY_LOCAL_MACHINE, Path, 0, KEY_ALL_ACCESS | KEY_WOW64_32KEY, &hKey)

Avoid Registry Wow6432Node Redirection

You can use RegistryKey.OpenBaseKey to solve this problem:

var baseReg = RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, RegistryView.Registry64);
var reg = baseReg.CreateSubKey("Software\\Test");

Reading 64bit Registry from a 32bit application

you have to use the KEY_WOW64_64KEY param when creating/opening the registry key. But AFAIK that's not possible with the Registry class but only when using the API directly.

This might help to get you started.

How to determine if a registry key is redirected by WOW64?

Your goal is not clear. Why do you need to enumerate registry keys in both the 32-bit and 64-bit registry views in a generic manner from a 32-bit application? What do you want to do with 64-bit values in your application? What would you do if there is some different values for x64 and x86 key? It feels like strange or rather wrong idea.

Keys are redirected for important reason: to not break behavior of x86 applications. For example: CLSID is used by COM to find proper implementation for a given interface. Among other, "proper" means that it might be run by caller code i.e. should be of the same platform. That's why there should be different sets of entries for x64 and x86. Reasons for other redirected keys are similar. Generally speaking, those redirected keys has to be different for x86 and x64 applications.

As Raymond Chen wrote, "On 64-bit Windows, 32-bit programs run in an emulation layer, and if you don't like that, then don't use the emulator" and I totally agree with his advice. So my best advice if you need something like this, is to do it from x64 application. But first reconsider whether you really need it.

EDIT: There is samDesired parameter of RegOpenKeyEx that you might find useful. Also take a look at "Accessing an Alternate Registry View" MSDN article.

Reading and writing to x86 and x64 registry keys from the same application

I might be misunderstanding what you're asking but if you're running in a 32bit process then all your keys will be in the Wow6432Node\xxxxx node anyway. So if you tried to copy them from HKEY_CURRENT_USER\Software\Classes\CLSID\{my clsid} (and didn't specify the 64 bit view manually) to HKEY_CURRENT_USER\Software\Classes\Wow6432Node\CLSID\{my clsid} you would be copying the same values. This code should work:

keyPath = @"Software\Classes\CLSID\" + clsid;
var regularx86View = RegistryKey.OpenBaseKey(RegistryHive.CurrentUser, RegistryView.Registry32);
// Note this calls HKEY_CURRENT_USER\Software\Classes\Wow6432Node\CLSID\{my clsid}:
var regularClassKey = regularx86View.OpenSubKey(keyPath, RegistryKeyPermissionCheck.ReadSubTree);

var regularx64View = RegistryKey.OpenBaseKey(RegistryHive.CurrentUser, RegistryView.Registry64);
// Note this calls HKEY_CURRENT_USER\Software\Classes\CLSID\{my clsid}:
var regularClassKey = regularx64View.OpenSubKey(keyPath, RegistryKeyPermissionCheck.ReadSubTree);

How can I read 64-bit registry key from a 32-bit process?

Your code is needlessly complex, largely because you are not taking advantage of the built-in TRegistry class which shields you from all the complexities of the low-level registry API. For example, consider the following code:

type
TRegistryView = (rvDefault, rvRegistry64, rvRegistry32);

function RegistryViewAccessFlag(View: TRegistryView): LongWord;
begin
case View of
rvDefault:
Result := 0;
rvRegistry64:
Result := KEY_WOW64_64KEY;
rvRegistry32:
Result := KEY_WOW64_32KEY;
end;
end;

function ReadRegStr(const Root: HKEY; const Key, Name: string;
const View: TRegistryView=rvDefault): string;
var
Registry: TRegistry;
begin
Registry := TRegistry.Create(KEY_READ or RegistryViewAccessFlag(View));
try
Registry.RootKey := Root;
if not Registry.OpenKey(Key) then
raise ERegistryException.CreateFmt('Key not found: %s', [Key]);
if not Registry.ValueExists(Name) then
raise ERegistryException.CreateFmt('Name not found: %s\%s', [Key, Name]);
Result := Registry.ReadString(Name);//will raise exception in case of failure
finally
Registry.Free;
end;
end;

The function ReadRegStr will return the string value named Name from the key Key relative to the root key Root. If there is an error, for example if the key or name do not exists, or if the value is of the wrong type, then an exception will be raised.

The View parameter is an enumeration that makes it simple for you to access native, 32-bit or 64-bit views of the registry. Note that native means native to the process that is running. So it will be the 32-bit view for a 32-bit process and the 64-bit view for a 64-bit process. This enumeration mirrors the equivalent definition in .net.

How to open a WOW64 registry key from a 64-bit .NET application

In the case where you explicitly need to read a value written by a 32 bit program in a 64 bit program, it's OK to hard code it. Simply because there really is no other option.

I would of course abstract it out to a helper function. For example

public RegistryKey GetSoftwareRoot() {
var path = 8 == IntPtr.Size
? @"Software\Wow6432Node"
: @"Software";
return Registry.CurrentUser.OpenSubKey(path);
}


Related Topics



Leave a reply



Submit