locked
Issue reading x64 Registry keys RRS feed

  • Question

  • I have a C# console app 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

     

    Monday, November 19, 2007 2:23 PM

Answers

  • The rules are pretty straightforward:

    • .NET app compiled for "x86":
      • Always 32-bit
      • On 32-bit platforms, accesses 32-bit registry
      • On 64-bit platforms, accesses 32-bit registry (inside Wow6432Node)
        • 64-bit registry inaccessible (without doing something weird)
    • .NET app compiled for "x64":
      • Always 64 bit
      • On 32-bit platforms, won't run
      • On 64-bit platforms, accesses 64-bit registry (not inside Wow6432Node)
        • If you want to get to the 32-bit registry, you need to do something weird
    • .NET app compiled for "AnyCpu"
      • Either 32 or 64 bit depending on platform
      • On 32-bit platforms, accesses 32-bit registry
      • On 64-bit platforms, accesses 64-bit registry (not inside Wow6432Node)
        • If you want to get to the 32-bit registry, you need to do something weird

    "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.

    Thursday, December 6, 2007 8:12 PM

All replies

  • 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!
    Wednesday, November 21, 2007 2:56 AM
  • 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 information from Registry I use the class RegistryKey. Here is the code

     

    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 Registry LOGSDIR 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.

     

     

    Friday, November 23, 2007 2:06 PM
  • 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 machine to x64 bit

    I execute the setup file on x64 machine. The installer creates registry keys under 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

     

    Saturday, November 24, 2007 9:47 PM
  • The rules are pretty straightforward:

    • .NET app compiled for "x86":
      • Always 32-bit
      • On 32-bit platforms, accesses 32-bit registry
      • On 64-bit platforms, accesses 32-bit registry (inside Wow6432Node)
        • 64-bit registry inaccessible (without doing something weird)
    • .NET app compiled for "x64":
      • Always 64 bit
      • On 32-bit platforms, won't run
      • On 64-bit platforms, accesses 64-bit registry (not inside Wow6432Node)
        • If you want to get to the 32-bit registry, you need to do something weird
    • .NET app compiled for "AnyCpu"
      • Either 32 or 64 bit depending on platform
      • On 32-bit platforms, accesses 32-bit registry
      • On 64-bit platforms, accesses 64-bit registry (not inside Wow6432Node)
        • If you want to get to the 32-bit registry, you need to do something weird

    "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.

    Thursday, December 6, 2007 8:12 PM
  • 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

    Monday, December 10, 2007 1:07 PM
  • 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.

    Tuesday, March 25, 2008 1:05 PM
  • 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.
    Tuesday, March 25, 2008 6:55 PM
  • 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 and so 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 of 64 bit OS of another machine but I am getting a return value of AccessDenied by using the above mentioned API. Cant we read the registry of 64 bit OS(Machine 1) using an application running on 32 bit OS(Machine 2)?

     

    Wednesday, March 26, 2008 4:42 AM
  • My scenario is different because we are running a 32bit app on x64 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
    Wednesday, August 20, 2008 4:28 AM
  • 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'd recommend 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
    Wednesday, October 15, 2008 11:06 PM
  • 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 TargetPlatform element was missing from the 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 by MikeOnline Tuesday, August 18, 2009 1:42 AM
    Tuesday, August 18, 2009 1:40 AM
  • I have another interesting problem related to the local machine key.

    I created a visual basic 2005 setup project that creates a context (right-click) menu on IE.  This worked great in Windows vista/xp.

    but on windows 7, the same setup package won't create a key under local machine\microsoft\internet explorer\extensions\extmenu

    do you know why?  I ran the setup.exe as administrator and all but my key doesn't get created.  thoughts?

    • Proposed as answer by Nedash Friday, May 14, 2010 6:54 PM
    Wednesday, April 14, 2010 3:24 PM
  • I resolved this issue from Configuration Manager. No need to change any code.

    Open Configuration Manager and add a new platform x86 in "Active solution platform" drop down. Select this new entry x86 as the platform for the project.

    I am using VS2010 on Windows 7 64bit.


    Ned
    Friday, May 14, 2010 7:13 PM
  • Hi,

    It seems that it goes in a lot of directions...

    I experience something similar that some of the people right here and I have some ideas about it.

    My setup is 2008 server for dev Environment with VS 2008 configured to any CPU in C# using framework 2.0

    I experience abit tricky situation : When I install My app on a 64 bit platforms, it installs in x86 program files but from task manager, it seems to be a 64 bit native app (no *32 beside the .exe). When writing the registry it writes in WOW6432, BUT when reading registry it reads from "standard" branch... not the WOW6432... not good. Can't run it on a 64 bit platforms without changing my code.

    I use a RegistryKey object. This object seems to come from Microsoft.Win32... Is there a Win64 class for using object from this class. And why redirection is only made when writing and not reading ??? Is this the source of our issues ?

    Xavier.

    Monday, May 17, 2010 6:35 PM
  • Hi Carlao,

     

    I have the same problem like yours. Please let me know the solution you gave to this problem.

    Thursday, October 21, 2010 1:56 PM
  • I had a similar problem where solution has been found, here's the topic :

    http://social.msdn.microsoft.com/Forums/en/csharplanguage/thread/f71f08d5-b3ff-4440-9073-05e438a8a3a5

     

    Tuesday, September 13, 2011 2:06 PM
  • I have a C# console app 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.
     
     

    .NET 4.0 has updated mscorlib to include the "Microsoft.Win32.RegistryView" enum which includes Registry.Default, Registry.Registry32, Registry.Registry64.  This eliminates the need to call the unmanaged RegOpenKeyEx in advapi32.dll via P/Invoke; thus, the process is now managed.  The Registry.Default will obviously use the RegistryView for the bitness of the .exe it is running in - NOT the bitness of the OS.  Remember that if you compile to "AnyCPU" and run on x64, your inherently using Registry64.  A sample of how to use this follows:

    // Use the default bitness of the .exe
    var registryBase = RegistryKey.OpenBaseKey( RegistryHive.LocalMachine, RegistryView.Default );
    
    // Use the 32-bit (WOW) registry 
    var registryBase32 = RegistryKey.OpenBaseKey( RegistryHive.LocalMachine, RegistryView.Registry32 );
    
    // Use the 64-bit registry 
    var registryBase64 = RegistryKey.OpenBaseKey( RegistryHive.LocalMachine, RegistryView.Registry64 );


     Registry.Registry32 will navigate to "HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node".  Note that you can access Registry.Registry32 from a 64-bit app if necessary.  However, access to Registry.64 is NOT permitted from a 32-bit app!
     
    HTH

    If this post is helpful, please mark it as such!
    Dave Black, MCPD, MCTS
    http://dave-black.blogspot.com


     
    • Proposed as answer by Dave Black Tuesday, October 11, 2011 1:49 PM
    • Edited by Dave Black Tuesday, October 11, 2011 2:07 PM
    Tuesday, October 11, 2011 1:49 PM
  • Dear, I have a similar problem, could you tell me how you solve the problem.

    Did you finally specify the path  as "HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\XXX", and which key are you using? KEY_WOW64_64KEY or KEY_WOW64_32KEY?

    Wednesday, March 28, 2012 11:38 AM
  • I used this solution (a mix of a lot of other research and Googling):

    If IntPtr.Size = 8 Then
       Uninstall = My.Computer.Registry.GetValue("HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall\Program Title", "UninstallString", Nothing)
    Else
       Uninstall = My.Computer.Registry.GetValue("HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\Program Title", "UninstallString", Nothing)
    End If

    IntPtr.size is equal to 8 on x64 systems and 4 on x86 systems. So that tells you what architecture Windows is based on.



    • Edited by ahwm Tuesday, July 3, 2012 8:36 PM
    Tuesday, July 3, 2012 8:34 PM
  • I am having a problem with this 64/32bit key support.

    I have a 32 bit application, which uses the KEY_WOW64_64KEY or KEY_WOW64_32KEY

    values to access the different key sets..

    all is ok. even when the key is duplicated in both sections. I can specifically retrieve either one..

    except on ONE Windows 2008 R2 datacenter machine, where there are two identical keys, 1 in each section.

    when I read the 64bit key explicitly, I get the 32bit key value.(with no errors, etc)

    if I remove the 32bit key value (rename it to another name), the code returns the 64bit key value.

    if I rename the 64bit key out of the way, leaving the 32bit key, the code fails to return the 64bit key.. good, and then retries for the 32 bit key successfully as expected.

    on my Windows 7 , or Windows server 2008 R2 standard 64 bit machines

    the same code, with the same values returns the 64bit key value when reading the 64bit key,

    and the 32bit key value when reading the 32bit key.    access to either key fails if not present

    (no automatic forwarding as I explicitly requested)

    any suggestions on how I can debug this? it only fails on this one system. I don't see anything different in the registry permissions,  the app is running as admin in all cases.

    it fails on different key data

    I cannot recreate this on another system

    thanks for any guidance

    Sam


    • Edited by sdetweil Friday, October 19, 2012 12:34 PM
    Friday, October 19, 2012 12:33 PM