Cant getValueNames() from HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Run - c#

I want to read all Values out of the Registry that are in the
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Run
I am trying to do this with the following Code:
RegistryKey key = Registry.LocalMachine.OpenSubKey(#"SOFTWARE\Microsoft\Windows\CurrentVersion\Run", false);
string[] values = key.GetValueNames();
But my values String is always empty.
The interesting part about that is, if I change the Code to
RegistryKey key = Registry.LocalMachine.OpenSubKey(#"SOFTWARE\Microsoft\Windows\CurrentVersion", false);
string[] values = key.GetValueNames();
I get the correct amount of ValueNames in CurrentVersion. Why does it not work in \Run?
If I change from LocalMachine to CurrentUser the \Run path works too.
RegistryKey key = Registry.CurrentUser.OpenSubKey(#"SOFTWARE\Microsoft\Windows\CurrentVersion\Run", false);
string[] values = key.GetValueNames();
Can someone tell me why my first CodeExample does not work? Thanks!

You don't provide details on whether your C# application is 32-bit (x86) or 64-bit (x64). If the application is 32-bit running on 64-bit Windows, registry calls for HKLM\Software are redirected to HKLM\Software\Wow6432Node. Microsoft call this the Registry Redirector. Only certain keys are redirected, the details are in the linked article.
If your application is 64-bit, these registry calls are not redirected.
You can test this by manually adding a single REG_SZ entry of say "TestWOW" to HKLM\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Run. Your 32-bit code should read this value (even though you actually asked for another registry key!).
If you can, re-compile your application as 64-bit. Now the same code will return the expected values from HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Run.
Unfortunately, I'm not aware of a mechanism to force Windows to NOT re-direct your registry calls to the Wow64 node for 32-bit applications running on a 64-bit OS.

Related

Does the registry HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\ show all subkeys

If i open this registry, and read out all subkeys, its different then my registry editor shows.
The way i open the registry and read out all subkeys :
//Get all results of the specified registery
string registry_key = #"SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall";
using (Microsoft.Win32.RegistryKey key = Registry.LocalMachine.OpenSubKey(registry_key))
{
foreach (string subkey_name in key.GetSubKeyNames())
{
using (RegistryKey subkey = key.OpenSubKey(subkey_name))
{
Console.WriteLine(subkey.Name);
}
}
}
This gives me the output from all subkeys in this registrykey.
As example i will take one out :
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\{FDCFD759-BA24-F0C8-FE83-43513EE6D443}
When i check my registry editor. And search this example it isnt in the given location, but it is in :
HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall\{FDCFD759-BA24-F0C8-FE83-43513EE6D443}
So coming to the question .....
Does the registry editor show all subkeys?
If there are any questions about my question or comments, i'd love to hear!
It's called "Windows on Windows", and it's by design.
Just like Program Files and Program Files (x86), the WOW6432Node key is special. When 32-bit processes try to read from HKEY_LOCAL_MACHINE\SOFTWARE\ they are instead directed into HKEY_LOCAL_MACHINE\SOFTWARE\WoW6432Node so they they don't try to accidentally do something that is only available for 64-bit processes.
By default Regedit on a 64-bit Windows machine shows you the 64-bit view of the registry.
32-bit applications running on 64-bit Windows sees the 32-bit view by default. These keys are under SOFTWARE\WOW6432Node in the 64-bit registry.
Uninstall information is stored in 4 places in the registry on a 64-bit machine: Under the HKEY_CURRENT_USER and HKEY_LOCAL_MACHINE roots in the 64 and 32-bit views.
Applications can decide which view they want to access by using the KEY_WOW64_64KEY or KEY_WOW64_32KEY flag when opening the key.

Registry redirection does not happen for HKEY_CURRENT_USER

I have the following code:
RegistryKey objRegKey = Registry.CurrentUser.OpenSubKey("SOFTWARE\\MySettings\\Dwm\\Preferences", true);
I have a registry key present under: HKEY_CURRENT_USER\SOFTWARE\MySettings\Dwm\Preferences and so this works fine.
When I change the above code to read from local machine instead of current user:
RegistryKey objRegKey = Registry.LocalMachine.OpenSubKey("SOFTWARE\\MySettings\\Dwm\\Preferences", true);
and create the following registry under:
HKEY_LOCAL_MACHINE\SOFTWARE\MySettings\Dwm\Preferences
The code returns null. I understand the reason being that due to registry redirection for 32 bit applications on a 64 bit OS, it tries to read the registry from:
HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432NODE\MySettings\Dwm\Preferences
and since the registry does not exists, it returns null.
The question is that why redirection only happens for HKEY_LOCAL_MACHINE and not for HKEY_CURRENT_USER?
Registry Redirection isn't a binary option - either present or not. Sometimes you want both 32-bit and 64-bit applications to have the same "view" of (part of) the registry and in other cases you do not.
That's why the specific keys affected by redirection are documented. HKEY_CURRENT_USER itself is shared, as is HKEY_CURRENT_USER\Software. However, HKEY_CURRENT_USER\Software\Classes\CLSID, which includes COM component registration data (which is necessarily 32/64 bit split) does perform redirection.
Or, to put it another way, if registry redirection was universal, you wouldn't need all of this convolution involving Wow6432Node, etc. You'd just have a 32-bit registry and a 64-bit registry.

Cannot read a registry value in Windows 8

I have following C# code, which reads the UAC state from registry in Windows 7
object obj = Registry.LocalMachine.GetValue(#"HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\Policies\System\EnableLUA", (long)1);
It works perfectly on Windows 7 with admin/not-admin accounts.
It always returns the default value I provide it under Windows 8.
The registry key is there. I can see its value with regedit. But the C# code does not read it. Can anybody tell why? It is a .net 4 application. The user account is unelevated admin.
It returns the default value (on both Windows 7 and 8). Here's the code that reads the correct Registry value on both Windows 7 and 8, without running as administrator.
object obj = Registry.GetValue(
#"HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\Policies\System\",
"EnableLUA",
(long)1);
Note that we call GetValue method on Registry, not on Registry.LocalMachine, and we pass key and value name as two separate parameters.
You need to require administrative privileges at least to be able to access the registry by default. Windows 8 developers possibly thinks it's safer to keep it that way.

Getting back "ResolveIOD" while trying to open HKLM\Software\Microsoft\Windows\CurrentVersion\Installer\ on Windows 7?

I'm trying to get at the UserData registry subkeys on a C# 3.5 application so I can look up the installed location of an external program to start it.
Doing something like this:
RegistryKey installerKey = Registry.LocalMachine.OpenSubKey("Software\\Microsoft\\Windows\\CurrentVersion\\Installer");
and then
RegistryKey userDataKey = installerKey.OpenSubKey("UserData");
returns null; if I go back and call installerKey.GetSubKeyNames() to figure out which subkey names are present under Installer it only returns one subkey name: ResolveIOD. I haven't been able to find what only being able to find this key indicates.
regedit does not show the ResolveIOD key being there, and it shows that much more than just that one key is present - UserData, Folders, Secure, etc are all there and not returned by GetSubKeyNames() either.
This is my first time accessing anything in the Installer section of the registry hive, so I've probably done something wrong. Is there some kind of special permission I have to request in order to read these (probably sensitive, security-wise) keys from a client application, or is this generally not an acceptable thing to do on Windows 7 and I should find an alternative way of figuring out where the program is located?
Because I'm seeing this mentioned on other registry questions: This is running as a 32-bit application on 64-bit Windows.
First, to ensure you are accessing the 64-bit registry rather than the Wow6432Node sandbox, use the RegOpenKeyEx function with KEY_WOW64_64KEY (http://msdn.microsoft.com/en-us/library/ms724878%28v=vs.85%29.aspx) included as one of the access options.
pinvoke.net has a C# example: http://www.pinvoke.net/default.aspx/advapi32/RegOpenKeyEx.html
Also note that with UAC enabled, an unelevated app will, at best, only have read access to HKLM.

Registry Key Access Differences Between Console and GUI App

I have a project which references another project in order to utilise some portions of code. One of the projects is a console application (that is the project type) but is made up of a significant code-base. The other is a GUI application that references this console application . The reason this is done is so the application can be run either as a console application or a GUI application.
When the GUI application runs it accesses the registry absolutely fine, but when I run the console version, which accesses the exact same code as the GUI application , it fails security-wise to get access to the registry keys. I'm assuming both the GUI and console application would run via the same user.
Here's what's failing (changes made to hide specific details):
String user = Environment.UserDomainName + "\\" + Environment.UserName;
RegistrySecurity rs = new RegistrySecurity();
rs.AddAccessRule(new RegistryAccessRule(user, RegistryRights.ReadKey | RegistryRights.Delete | RegistryRights.WriteKey | RegistryRights.FullControl, InheritanceFlags.None, PropagationFlags.None, AccessControlType.Allow));
mapsynckey = Registry.LocalMachine.CreateSubKey("SOFTWARE\\AppPath\\AppName\\");
UserName = mapsynckey.GetValue("user").ToString();
Password = mapsynckey.GetValue("pass").ToString();
SyncFolderPath = mapsynckey.GetValue("syncfolderpath").ToString();
Ignore the access rights, I've just been trying every single one hence the random mixture.
The error I receive is as follows:
Access to the registry key 'HKEY_LOCAL_MACHINE\SOFTWARE\AppPath\AppName' is denied
Here's the other thing. I can't find the entries anywhere in the registry, not even under the 64-bit section. However, I am loading the registry key details into the application which are shown fine, but if I browse the registry, they're not there.
I'm completely stumped, I've spent the last 3 hours working on this with no clue what's going on.
at ApplicationSettings..ctor() in C:\Projects\MapSync\MapSyncConsole\ApplicationSettings.cs:line 34
at ApplicationSettings.get_Instance() in C:\Projects\MapSync\MapSyncConsole\ApplicationSettings.cs:line 47
at MainApplication..ctor(Boolean forceDownload) in C:\Projects\MapSync\MapSyncConsole\MainApplication.cs:line 27
at MapSyncConsole.Program.Main(String[] args) in C:\Projects\MapSync\MapSyncConsole\Program.cs:line 21
First and foremost: Did you check the (UAC) virtualized registry locations? (See here). Registry uses a similar mechanism as file system for transparent redirection.
Additionally:
which token is your process running under, elevated or not? Assuming you have UAC enabled: Do you start the console app from a elevated prompt (seems not)? I guess you start the UI version by double-clicking?
less probable: does one of the executables have an embedded manifest which manipulates the elevation behavior?
less probable: do the processes (console vs. UI) target different processor architectures?
You can't call CreateSubKey in HKLM without administrator privileges.
You should consider switching to HKCU.

Categories

Resources