I have a C# consoleapp compiled with .Net 2.0 in 32 bit machine. This app run fine in 32bit machine.But when I run in x64 machine I get some issues.
I figured out that the information about app was installed correctly on HKLM\SOFTWARE\Wow6432Node\MyCompany\MyApp\ registry key.
But in my code I have hard coded the following string "SOFTWARE\MyCompany\MyApp"
I thought that WOW64 could translate correctly from "SOFTWARE\MyCompany\MyApp" to SOFTWARE\Wow6432Node\MyCompany\MyApp. I am using the class RegistryKey from the Framework. I know that all is correct because it works in 32bit but seems that I am missing something with x64. I got a look at Registry Redirection and Reflection but could not see a solution. Any idea?
Thanks.
www.byteshift.com
| | carlao | The rules are pretty straightforward:
"Something weird" technically requires passing a special flag to RegOpenKeyEx to obtain the alternate registry view. .NET doesn't expose any function that will do this nicely, so you'd have to drop to p/invoke to get there.
Alternatively if you want to get to the 32-bit registry from a 64-bit/AnyCpu app, you can hardcode the "Wow6432Node" path in (since the 32 bit registry is visible from 64 bit, but not the reverse), but MS explicitly recommends against this. | | Miral | Hi carlao,
I'm not sure about what exactly you mean by "some issues", could you please clarfiy?
To troubleshoot this issue, we really need the source code to reproduce the problem, so that we can investigate the issue in house. It is not necessary that you send out the complete source of your project. We just need a simplest sample to reproduce the problem. You can remove any confidential information or business logic from it. Thanks! | | Feng Chen | Let me try to explain the error that get when the app tries to read Registry.
I have a C# console app.
I installed my app on x64 using InstallShield. Then I open Registry and I can see some information about my app at
HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\xxx\yyy
By the other side, IS installs my app on x32 and when I open Registry and see the same information at
HKEY_LOCAL_MACHINE\SOFTWARE\xxx\yyy
where xxx = my company and yyy = my app
Until here, nothing new..
To read the informationfrom Registry I use the class RegistryKey. Here is thecode
Code Block
public string GetMyLogsDir() { // Determine location to log to. string logspath = GetRegistryValue("SOFTWARE\\XXX\\YYY", "LOGSDIR"); return logspath; }
public string GetRegistryValue(string key, string name) { string retVal = ""; infoMessage = "";
// Open the registry key, always in HKLM. RegistryKey rootkey = Registry.LocalMachine; // Open a sub key for reading. Debug.WriteLine("Key: " + key); RegistryKey subkey = rootkey.OpenSubKey(key); // If the RegistryKey doesn't exist return null if (subkey == null) { return retVal; } else { try { Debug.WriteLine("Subkey: " + name); // Check for proper registry value data type RegistryValueKind valKind = subkey.GetValueKind(name); if (valKind == RegistryValueKind.DWord || valKind == RegistryValueKind.String) retVal = subkey.GetValue(name).ToString(); } catch (Exception ex) { ... } } return retVal; }
In RegistryLOGSDIR key I have the string
C:\Program Files (x86)\xxx\yyy\logs
When I run the app under x32 the function correctly returns C:\Program Files\xxx\yyy\logs
that is correct. But under x64 the function returns an empty string. I guess that WOW64 should replace my string
HKEY_LOCAL_MACHINE\SOFTWARE\xxx\yyy by this one
HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\xxx\yyy
One solution should be the code check if it is running under x64 and hard code Wow6432Node by hand. But the WOW64 docs says that WOW64 intercept any x32 call to Registry and replace by the correct value. Why I can not see this happening in my app?
Thanks.
| | carlao | More details...
I could make a very interesting test to double check the issue regarding to read Registry keys.
Environment.
- Windows 2003 x64 running .Net 2.0 x64
- C# console application 32 bits.
- Visual Studio 2005 32 bits.
- My development environment is XP 32bits.
Scenario 1.
I create a VS.Net setup project and configure the target machineto x64 bit
I execute the setup file on x64 machine. The installer creates registry keysunder HKLM\SOFTWARE\COMPANY\APP and copy files to Program Files\Company\App. That is correct because the target machine is x64.
When I try to run my .Net 32 bit app, surprise to see it can read the keys on registry and find correctly the directories in Program Files. In my opinion, I should get an error regarding to not find Wow3264Node key and not find directory Program Files (x86). Why I don’t get an error? Well I got an error in the point where my app tries to load a x32bit dll but that is another history that I will not put in discussion now.
Scenario 2
I get the same setup project and configure the target machine to x32 bit.
I execute the setup file on x64 machine. The installer creates registry keys under HKLM\SOFTWARE\Wow3264Node\COMPANY\APP and copy files to Program Files (x86)\Company\App. Again, the installer occurred as expected.
But when I try to run my .Net 32bit app, surprise to see it can not find keys on registry under Wow3264Node key. The keys were correctly created in Registry but the RegistryKey class from .Net Framework can not find the key and return a null string. Why this error?
It seems that Wow64 is not hocking calls to registry correctly where it should replace calls to Software\Company into Software\Wow3264Node\Company.
Any will be appreciate idea?
Thanks.
www.byteshift.com
| | carlao | The rules are pretty straightforward:
"Something weird" technically requires passing a special flag to RegOpenKeyEx to obtain the alternate registry view. .NET doesn't expose any function that will do this nicely, so you'd have to drop to p/invoke to get there.
Alternatively if you want to get to the 32-bit registry from a 64-bit/AnyCpu app, you can hardcode the "Wow6432Node" path in (since the 32 bit registry is visible from 64 bit, but not the reverse), but MS explicitly recommends against this. | | Miral | Hi Miral, You are right. My problem was a conbination (or a mixture) of options. I am using AnyCpu. InstallShield installs the app as 32-bit. W2k3 x64 uses .Net 2.0 64-bit. What happened is that my app was installed as 32-bit but as a .Net app compiled as AnyCpu, it will run as 64-bit. As a 64-bit the app will try to access the regular path keys in Registry. But all the app information was installed on WoW6432Node. This way the app will fail when it tries to read registry. Now I know where is the problem and how to fix it. Thanks for your time.
www.byteshift.com
| | carlao | Hi,
I have a similar kind of problem. We are trying to read 64 bit machines registry from a 32 bit machine(application is running on a 32 bit machine) but the return value form the API(RegOpenKeyEx ) is AccessDenied. We have appended WOW6432NODE in the registry path like SOFTWARE\WOW6432NODE\SERTEST\Path1 but still we are getting the same resultID. I think the problem is with the access permissions we are using. This is how we are calling the API:
hr = RegOpenKeyEx ( hKeyBase,
newPath,
0,
KEY_ENUMERATE_SUB_KEYS |
KEY_QUERY_VALUE,
hKey);
Can you tell me how you have solved your problem so that it will be helpful for me in solving mine?
Thanks in advance. | | qq.raghuvamsi | First of all, that's not .NET code, so you're off-topic  Secondly, if you're on a 32-bit version of Windows then there is no 64-bit registry, and nothing you can do will make one magically appear. (32-bit Windows cannot run 64-bit apps, at all.) Thirdly, 32-bit apps running on 64-bit Windows cannot use Wow6432Node; that's an artifact that only exists in the 64-bit registry, since it's the "real" registry on 64-bit Windows. (And technically you're not supposed to use it at all; it's an implementation detail rather than an approved interface.) Finally, if you are definitely running on 64-bit Windows, you can use either the KEY_WOW64_32KEY flag (which says you want to access the 32-bit registry regardless of whether your app is 32 or 64 bit) or the KEY_WOW64_64KEY flag (the same, but for the 64-bit registry). Just remember that these flags cannot be passed if you're not running on 64-bit Windows. | | Miral | Hi Miral,
First of all Thanks for ur inputs. Yes its a C++ code but after seeing this API(RegOpenKeyEx), I thought I have a similar kind of problem andso I have posted my query. Sorry if have violated ur polocies. Yes 32 bit Windows wont have 64 bit registry. But what our application does is, it will try to read the registry of another 64 bit machine. The application is running on my machine(32 bit) and I am trying to read registry of64 bit OS of another machine but I am getting a return value of AccessDenied by using the above mentioned API. Cant weread the registry of 64 bit OS(Machine 1)using an application running on 32 bit OS(Machine 2)?
| | qq.raghuvamsi | My scenario is different because we are running a 32bit app onx64 bit platform. I could fix my issue using the flags mentioned by Miral. But note that this flag is only valid with x64 platforms. I mean, if you use this flag in your 32bit app and try to compile you will get a compile error. I short, I guess you can not use a 32bit machine to access a 64bit machine. .Net Senior Developer | | carlao | Easy solution is to set the Advanced Compile properties to x86 and the .NET Microsoft.Win32.Registry.LocalMachine... will work fine. If your application that reads other 32bit applications needs to be 64bit, then the solutions used above would work. If you want to keep your app 64bit but still need to access 32bit apps registry, then I'drecommend using "Wow6432Node" reference in .LocalMachine -- I know this is not recommended by Microsoft because it "might" change in some distant future -- even if it changed for Windows 7, ask youself this -- "when was the last time I didn't need to change any part of my software to be compatible with the next Windows OS?"
If Microsoft don't lead by example, I don't see why we should -- besides, it justifies a new revenue source ;) (hmmm...sounds familiar).
Rob Developer | | Oroborus | I encountered a similar issue, where a C# app written for platform x86 was able to read subkeys directly under HKEY_LOCAL_MACHINE\SOFTWARE on Vista 64 and WIndows 7 (64-bit). It should not have been able to do this.At first, I could not figure out why it could not read the key HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node.
I finally discovered the cause: I had changed the C#Project File (.csproj) with a text editor, to target x86 rather than AnyCPU. But changing the target platform this way is insufficient. Visual Studio 2005 will appear to be building for Platform x86, but in actuality it will build for Platform AnyCPU.
Using WinMerge to compare csproj files, I found that the TargetPlatformelement was missing fromthe Debug and Release configuration groups within the csproj file. Apparently, this element is not needed or established for a new C# app that defaults to platform AnyCPU, but must be explicitly included for targeting Platform x86.
I used Configuration Manager within Visual Studio 2005 to remove the x86 target platform and add then add it back in. My x86 app now automatically looks to Wow6432Node under HKLM\SOFTWARE, as expected.
- Michael- Proposed As Answer byMikeOnline Tuesday, August 18, 2009 1:42 AM
-
| | MikeOnline |
|