Here's my code:
Microsoft.Win32.RegistryKey key = Microsoft.Win32.Registry.LocalMachine.OpenSubKey(#"SOFTWARE\ADM");
The registry entry exists on the machine. key is always null.
I don't think that this is a security issue. I'm running as Administrator. (I've even explicitly ran the assembly under Administrator mode).
I'm using Visual Studio 2010 running on Windows 7 64bit.
The problem is that I'm running 64bit and my app is compiled as 32bit.
The key being read by:
Microsoft.Win32.RegistryKey key =
Microsoft.Win32.Registry.LocalMachine.OpenSubKey(#"SOFTWARE");
Is not HKLM\SOFTWARE but instead HKLM\SOFTWARE\Wow6432Node\. Compiling the application as x64 solves the problem.
Try opening each registry key individually like this
Microsoft.Win32.RegistryKey key1 = Microsoft.Win32.Registry.LocalMachine.OpenSubKey(#"SOFTWARE");
Microsoft.Win32.RegistryKey key2 = key1.OpenSubKey(#"ADM");
Instead of using the string #"SOFTWARE\ADM";
I've run your code with a different application name (one I have a key for) and everything was ok, so the code is ok, but I tested this on Win XP.
When studying writing to the registry, I found this article about registry virtualization in Windows 7 that might cause your problems:
Windows Vista and later versions of Windows improve application compatibility for these applications by automatically redirecting these operations. For example, registry operations to the global store (HKEY_LOCAL_MACHINE\Software) are redirected to a per-user location within the user's profile known as the virtual store (HKEY_USERS\_Classes\VirtualStore\Machine\Software).
Related
I have changed the registry manually for all the machines. It works on my own machine with Visual Studio. I tried another Win 10 Virtual machine and a Win 7 pro on a remote desktop, but it does not work on all of them. However, I have used the remote desktop to run other exes with similar functions and it works.
I have a guess: does the .vshost.exe should also be added to the FEATURE_BROWSER_EMULATION list?
UPDATE: I have noticed the difference of whether the registry key is in Wow6432node according to http://weblog.west-wind.com/posts/2011/May/21/Web-Browser-Control-Specifying-the-IE-Version . And it works after adding the registry key to the Wow6432node. So a new question arouses: When will the webbrowser runs in x86 and when x64? And when will the managed code runs in x86 and when x64? According to my practice, adding registry keys to the path without wow6432node sometimes work and sometimes doesn't.
In the task manager, you will see name of the executable file. If you're running the app with Visual Studio (debug mode), the name will be "application_name .vshost.exe". In this case, you should name the registry key in that way. Otherwise, use name of the executable file generated by debugging, and run it.
Please correct me if I'm wrong on this, as I'm certain I read it somewhere: Registry virtualization is disabled for Windows Services. Also, virtualization is disabled for x64 binaries.
I have a windows service written in C# that needs to load a value from HKEY_LOCAL_MACHINE\SOFTWARE. When I compile the service as x86 and start it, it fails to read the value. When I compile the same code as x64 and start it, it reads the value just fine. I want my service to be able to run on x86 machines in addition to x64 machines, but it needs to also be able to read this value. How do I get my windows service to read the value non-virtualized?
Registry virtualization is disabled for Windows Services. Also, virtualization is disabled for x64 binaries.
Yes, you're right, it's disabled for 64 bit processes and for "processes that are not interactive, such as services".
Take a look to my previous post here on SO for some details about registry views. Please do not confuse views with virtualization. They're different. Views are needed to isolate 32-bit application from 64-bit applications.
In C# you can do the same simply asking the OS to open the 64 bit version of the registry:
RegistryKey baseKey = RegistryKey.OpenBaseKey(
RegistryHive.LocalMachine, RegistryView.Registry64);
RegistryKey key = baseKey.OpenSubKey("Software", false);
object value = key.GetValue("");
If your application/service will run in a 32-bit machine you'll always get the normal registry even if you ask for RegistryView.Registry64. When running in a 64-bit machine you'll always get the normal version of the registry (= 64-bit version).
Side question: why do you need to compile your application as X86 or X64? Can't simply keep AnyCPU?
Virtualization has a different purpose and it's not intended to separate the registry from 32 bit applications but to increase compatibility with legacy applications, we all hope that a 64 bit native application will use the registry in the correct way. To access the non-virtualized version of the registry you have to open the registry key using REG_KEY_DONT_VIRTUALIZE flag. It's not possible to use this flag with Microsoft.Win32 classes so you have to DllImport them and P/Invoke.
I am running 64-bit Windows, and I want to create the registry key HKCU\Software\Classes\Wow6432Node\CLSID\{myguid}\InprocServer32 using C#.
What registry key should I tell it to write, so that it will be redirected to the above key? This should also work on 32-bit Windows.
I am compiling my app to target x86.
If you are using .net 4 you should make use of the RegistryView enumeration.
Pass RegistryView.Registry32 when you call OpenBaseKey. Use HKCU\Software\Classes\CLSID{myguid}\InprocServer32 as your key and let the redirector do the work.
If you are using an older version of .net then I am afraid you will need to p/invoke the native Win32 API.
If you happen to be targetting x86 then you don't need to do anything. The registry redirector will do the right thing and redirect your registry access to the 32 bit view of the registry. You only need to take the steps outline above from a 64 bit process.
64-bit versions of Windows emulate 32-bit functionality through the "Windows on Windows" (WoW) subsystem.
In the case of the registry, they move the 32-bit keys over to a special subkey for compatibility reasons. It will automatically redirect 32-bit registry operations to HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node. More details can be found on the MSDN topic about the Registry Redirector.
You can use the RegistryView enum on RegistryKey.OpenBaseKey to open the 32-bit view explicitly and access HKCU\Software\Classes\CLSID{myguid}\InprocServer32 directly. This will automatically access the WOW64 node on 64-bit systems and the normal key on 32-bit systems.
Since you are targetting x86, simply using HKCU\Software\Classes\CLSID\{myguid}\InprocServer32 will work on all platforms.
By default your C# application is compiled using "Any CPU" (this is the default -- it means that your program will run as a x86 exe on x86 machine, and x64 on x64 machines). What you want to do is change the setting to Win32.
Now your program will always run as an x86 exe, so it will be automatically redirected by windows the WOW6432Node. When you access the HKCU\Software\Classes\CLSID{myguid}\InprocServer32 on an x64 machine you will be redirected to the desired key.
I have an application (written in C#), which runs on an Windows Server 2008 (64bit). In this application I must check some registry keys regarding the IIS. Among others I want to access the key HKEY_LOCAL_MACHINE\Software\Microsoft\InetStp\Components\WMICompatibility"
to check if the IIS 6 compatibility mode is enabled or not. For this I use Registry.GetValue of Microsoft.Win32.
For some reasons the solution must be compiled with x86. The consequence is, that it is no longer possible to access HKEY_LOCAL_MACHINE\Software\Microsoft\InetStp\Components but it is still possible to read key from HKEY_LOCAL_MACHINE\Software\Microsoft\InetStp. When compiling it with "AnyCPU"-flag the registry-access works fine.
So what is the reason for this behavior? Is there a solution or workaround for this problem?
You are falling foul of registry redirection.
The best solution is to open a 64 bit view of the registry, like this:
using Microsoft.Win32;
...
RegistryKey registryKey =
RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, RegistryView.Registry64).
OpenSubKey(#"Software\Microsoft\InetStp\Components");
object value = registryKey.GetValue(#"WMICompatibility");
If you want your code to work on both 32 and 64 bit machines then you'll need to code some switching between registry views.
Note: The capability of accessing 64 bit views from 32 bit processes was only added to the .net libraries in .net 4. It seems that prior to that you needed to use native APIs, e.g. with P/Invoke.
Windows x64 has a separate node for x86 programs (not the brightest idea)
All registry keys will be under HKEY_LOCAL_MACHINE\Software\WOW6432Node
More about this issue:
How to view the system registry by using 64-bit versions of Windows
The program still "thinks" it's writing to the same path.
I'd suggest you fix your setup (dispatch) program to write the initial settings in the right place.
Edit, Some "information" from MSDN:
Registry Keys Affected by WOW64
I have an application that is supposed to read from the Registry and when executing a console application my registry access works perfectly.
However when I move it over to a test this returns null:
var masterKey = Registry.LocalMachine.OpenSubKey("path_to_my_key");
So my question is:
Does Visual Studio run Tests with a less privileged process?
I tested to see what user this gave me: var x = WindowsIdentity.GetCurrent().Name; and it gives me the same as in the console application. So I am a bit confused here.
I am using MS Test Framework and the machine is Windows 2003 64 Bit.
It is not a security issue. It's the fact that you are running on a 64-bit operating system. 64-bit apps have a different view of HKLM\Software than 32-bit apps. 64-bit apps get the "normal" view, 32-bit apps are redirected to HKLM\Software\Wow6432Node. The EXE determines the bit-ness of the process, it will be different when mstest runs the code. 32-bit, probably.
You'll need to create the key you are trying to read in the Wow6432Node tree. Or make the regular app have the same bit-ness, Project + Properties, Build tab, Platform Target = x86. Also changeable on-the-fly with Corflags.exe.
I would say yes. Why do you expect anything different?
It would have to be this way to be Windows Logo compliant.
It's also good from a security viewpoint.
Visual Studio .NET is Windows Logo compliant, so you would expect that it runs as a restricted user
http://blogs.msdn.com/vcblog/archive/2006/09/06/742187.aspx