I have already looked at existing topics, so please try to refrain from dropping links here.
I want to get the value of a registry key - plain and simple. Here is what I have so far.
Registry:
1) Made a key under
Current_User\Software\Custom_Subkey\Custom_Value\Custom_key\string_value
I am trying to find the string_value
string reg_subKey = "Software\\Custom_Subkey\\Custom_Value";
RegistryKey root = Registry.CurrentUser.CreateSubKey(reg_subKey);
foreach (string keyname in root.GetValueNames())
{
textBox4.AppendText(keyname.ToString() + Environment.NewLine);
// Appends the following data to textBox4 once the foreach is completed:
// Header1
// Header2
// Header3
// Header4
// Header5
// Now I want to get the VALUES of each header:
using (RegistryKey key = root.OpenSubKey(keyname))
{
**// THIS LINE GETS HIGHLIGHTED WITH THE FOLLOWING ERROR:
"Object reference not set to an instance of an object.**"
MessageBox.Show(key.ValueCount.ToString());
}
}
Hopefully this is a simple fix. I look forward to hearing your responses.
Thanks,
Evan
I believe you want root.GetSubKeyNames() in the loop not GetValueNames()
While values is working to get the values I would suggest the following loop:
foreach(string keyname in root.GetSubKeyNames())
{
// use key to get value and set textbox4
using (RegistryKey key = root.OpenSubKey(keyname))
{
MessageBox.Show(key.ValueCount.ToString());
}
}
The OpenSubKey method does not throw an exception if the specified subkey is not found. Instead, it simply returns null. It's your responsibility as a programmer to ensure that the appropriate key was found and opened by checking the return value of the method call.
Thus, my suspicion is that the registry key that you've specified is invalid. Open up Registry Editor (regedt32.exe), and verify that you can find the key in the registry exactly as written.
If you find that the registry key is indeed located exactly where you thought it was, then the problem may be related to the WOW64 subsystem, which allows 64-bit versions of Windows to run 64-bit apps. If the value was written to the registry by a 32-bit program, you won't be able to read it with the above code from a 64-bit program (or vice versa). The simplest way to check this is to change the compilation settings for your project. For example, if you're currently compiling for x86, then change to compiling for x64, or vice versa. Registry redirection may also be getting in your way; this will check for that as well.
I wanted the very same thing and your code helped me, but as you said, it didn't work properly. So, I made some modifications and I think it works fine now! Try this:
//Just make the reference until "custom_subkey", not to the next one ("custom value")
string reg_subKey = "Software\\Custom_Subkey";
RegistryKey root = Registry.CurrentUser.CreateSubKey(reg_subKey);
//Use GetSubKeyNames, instead of GetValueNames, because now you are in a higher level
foreach (string keyname in root.GetSubKeyNames())
{
using (RegistryKey key = root.OpenSubKey(keyname))
{
foreach (string valueName in key.GetValueNames())
{
MessageBox.Show(valueName);
MessageBox.Show(key.GetValue(valueName).ToString() );
}
}
}
Related
I'm trying to fetch some data on the Office Click-To-Run currently installed.
I've read these posts : Can't Read Registry Key or OpenSubKey() returns null for a registry key that I can see in regedit.exe
I'm on Windows 10 64bit. My application is an Outlook add-in, so I can't change the target platform (32/64bit), it's the Host that determine if I'm running in 32bit or 64bit. So I've to handle both cases.
So I've this (test) code :
using (var hklmTest64 = RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, RegistryView.Registry64))
{
var test = hklmTest64.GetValue(#"SOFTWARE\Microsoft\Office\ClickToRun\Configuration\AudienceData");
if (test == null)
{
using (var hklmTest32 = RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, RegistryView.Registry32))
{
test = hklmTest32.GetValue(#"SOFTWARE\Microsoft\Office\ClickToRun\Configuration\AudienceData");
}
}
}
So I first fetch the registry key using the 64bit view, then if null I retry using the 32bit view.
Problem: test is always NULL.
Of course the key exists and I can see it using regedit:
Of course I first tried simple code that until now always worked for me, but doesn't work to fetch this key:
test = Registry.LocalMachine.GetValue(#"SOFTWARE\Microsoft\Office\ClickToRun\Configuration\AudienceData");
test = Registry.GetValue(#"HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Office\ClickToRun\Configuration", "AudienceData", null);
And more strange thing, it's that I had exactly the same problem for fetching the windows build number. This code was not working :
var wBuild = Registry.LocalMachine.GetValue(#"SOFTWARE\Microsoft\Windows NT\CurrentVersion\ReleaseId");
But this one works perfectly for windows build (not for outlook key):
var wBuild = Registry.GetValue(#"HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion", "ReleaseId", null);
Any idea how to fetch this registry key ?
UPDATE 1
See the post C# get Office ClickToRun Registry Key returns null
But reading the post, my code using RegistryView.RegistryXX should work...
UPDATE 2
I've reprod the problem using LinqPad, so this is not due to the Outlook host / add-in. I tried to reprod in a .NET Fiddle but indeed the code is not allowed to access the registry :)
I can get the correct values using P/Invoke like explained in this article. So for me it's clearly a 32/64bit (wow6432node) problem.
you dont need
RegistryKey.OpenBaseKey
just use Registry.GetValue(keyName, valueName, defualt value)
this is working example
string InstallPath = (string)Registry.GetValue(#"HKEY_LOCAL_MACHINE\SOFTWARE\" + path, "ActivationCode", null);
I can get the correct values using P/Invoke like explained in this article. So for me it's clearly a 32/64bit (wow6432node) problem.
I have a program which i try is to read all the keys under classesroot but when i do it with GetSubKeyNames() many keys are skipped i only get the key which contains another sub key on it.
RegistryKey key = Registry.ClassesRoot;
foreach (string tempKeyName in key.GetSubKeyNames())
{
MessageBox.Show(tempKeyName);
}
enter image description here
This code shows all the registry keys under HKEY_CLASSES_ROOT. If it doesn't work for you, edit your question telling us Windows version and maybe if you are under a corporate network.
RegistryKey rk = Registry.ClassesRoot;
// Print out the keys.
PrintKeys(rk);
PrintKeys:
static void PrintKeys(RegistryKey rkey)
{
// Retrieve all the subkeys for the specified key.
String[] names = rkey.GetSubKeyNames();
Console.WriteLine("Subkeys of " + rkey.Name);
Console.WriteLine("-----------------------------------------------");
// Print the contents of the array to the console.
foreach (String s in names)
{
Console.WriteLine(s);
}
}
Source:MSDN
JANUARY 2022 - This issue is due to breaking changes introduced in the framework's registry searching library that apparently are not well known
For those searching and still coming up with incorrect registry key results this is due to the 32/64 redirecting in place by Microsoft. This means the old route of iterating for a key in the ClassesRoot hive using Registry.ClassesRoot could unknowingly search the Wow6432 key instead.
The new route is to look it up using the base key while explicitly defining where it should search. Here's the current way to correctly search for a key if you are having this trouble:
RegistryKey.OpenBaseKey(RegistryHive.ClassesRoot, RegistryView.Registry64)
Note the use of the RegistryKey static member instead of Registry
You can explicitly tell it to look in Registry32, Registry64, or Default - the later of which is what the old process of Registry.ClassesRoot appears to follow.
I am working on a project that will allow me to delete the registry key from a Windows 7 PC. Specifically I am trying to make a program that will allow me to delete a profile from the machine via the ProfileList key. My problem is no matter what I try I can't seem to read the key correctly which I want to do before I start randomly deleting stuff. My code is
RegistryKey OurKey = Registry.LocalMachine;
OurKey = OurKey.OpenSubKey(#"SOFTWARE\Microsoft\WindowsNT\CurrentVersion\ProfileList", true);
foreach (string Keyname in OurKey.GetSubKeyNames())
{
MessageBox.Show(Keyname);
}
This code runs but doesn't return anything (No MessageBox). Any ideas why not?
EDIT:
I got the top level keys to load thanks to you all but it does only show the folder/key names (Ex: S-1-5-21-3794573037-2687555854-1483818651-11661) what I need is to read the keys under that folder to see what the ProfilePath is. Would there be a better way to go about that?
As pointed out by Lloyd, your path should use "Windows NT". In case of doubt, always use regedit to go inspect the registry manually.
Edit: To go with your edit, you can simply GetValue on the keys you find, the following code should do what you're looking for:
RegistryKey OurKey = Registry.LocalMachine;
OurKey = OurKey.OpenSubKey(#"SOFTWARE\Microsoft\Windows NT\CurrentVersion\ProfileList", true);
foreach (string Keyname in OurKey.GetSubKeyNames())
{
RegistryKey key = OurKey.OpenSubKey(Keyname);
MessageBox.Show(key.GetValue("KEY_NAME").ToString()); // Replace KEY_NAME with what you're looking for
}
Windows NT
Please do not miss space
I'm currently building a registry explorer, mostly because I want to support some much better searching operations. Like 'find all' and regular expressions. One problem I'm facing is that some keys throw a security exception when opening. I HAVE TRIED running the app with administrator priviledges, my user account is an administrator also. I embedded a manifest with "requireAdministrator" requested priviledges. I have also tried setting the ClickOnce security settings to Full trust, which is incompatible with requireAdministrator, or so Visual Studio tells me.... Nothing seems to help with avoiding this exception.
I would just like to iterate over all of the keys. I do not wish to add/delete keys. If a user wishes to delete a key and does not have permission to do so, it would display an error message. I just want to be able to have unrestricted READ access. Is this possible?
FTR: I'm on Win7 x64 and using Vs2010u and project is written in C# on .net 4.0. If regedit is capable of reading all keys even if it doesn't let you edit some of them. It would seem appropriate that we too can make an app to do the same thing. Though I'm finding it very difficult, and there doesn't seem to be any real help on the www. Only link-link circles, yay.
[EDIT]
Here's the code that reads the keys:
private void IterateSubKeys(RegistryKeyModel key) {
var subKeys = key.Key.GetSubKeyNames();
var values = key.Key.GetValueNames();
foreach (var valuename in values) {
try {
var valueKind = key.Key.GetValueKind(valuename);
var value = key.Key.GetValue(valuename);
key.Values.Add(new RegistryValueModel(valuename, value, valueKind));
}
catch { }
}
foreach (var keyname in subKeys) {
try {
var subkey = key.Key.OpenSubKey(
keyname,
RegistryKeyPermissionCheck.ReadSubTree,
RegistryRights.ReadKey);
key.SubKeys.Add(new RegistryKeyModel(subkey));
}
catch { Console.WriteLine("Error reading key: {0}", keyname); }
}
}
This is by design. There are lots of security related keys that can only accessible to the System account. You can't use that account. Regedit can't read these keys either, they are just not visible. Avoiding the expensive exception is going to require pinvoke.
I'm trying to set a registry key in my C# code, but it doesn't work all the time. Sometimes it does work, sometimes it doesn't. I'm starting to get crazy...
In previous projects I had no problems writing and reading to the registry, but I do now.
Here's the code I'm using:
string newVersion = "10A";
RegistryKey key = null;
try
{
key = Registry.CurrentUser.CreateSubKey("Software\\stuff1\\stuff2 " + newVersion + "\\" + newVersion + "\\stuff3\\Settings", RegistryKeyPermissionCheck.ReadWriteSubTree);
key.SetValue("CopyConvertDone", "1", RegistryValueKind.String);
key.Flush();
rep.Message("CopyConvertDone registry key set for revision: " + newVersion);
}
catch (Exception e)
{
rep.Error(e);
}
finally
{
if (key != null)
{
key.Close();
}
else
{
rep.Error("Registry key is set to null.");
}
}
What I already tried but didn't work:
- Instead of using CreateSubKey I tried OpenSubKey with the write-parameter set to true.
- Added the .Flush() method.
- Did a Thread.Pause(2000) to give it some time before progressing my program (which needs this registry key)
I don't get any error and the subkey already exists, but the value (CopyConvertDone) doesn't.
Can anyone see a problem in this code and has a possible solution?
The code looks alright to me, however if it's working some of the time then perhaps use Process Monitor to see what calls are being made to the registry and what is succeeding/failing.
Had something similar happen to me just now, and using Process Monitor as suggested by Antony I discovered Windows 7 was redirecting my writes to a key under HKCU\Software\Classes\VirtualStore\MACHINE.
Just a pointer in case anybody else has this issue.
Looks correct. Maybe try to remove Flush. From MSDN: An application should only call Flush if it must be absolute certain that registry changes are recorded to disk. In general, Flush rarely, if ever, need be used.
Your already closing the RegistryKey in the finally statement.