OpenSubKey() Registry key's “Absolute Path”? - c#

Using Microsoft.Win32.RegistryKey C# functions which require a registry path, like OpenSubKey(), using a path like
#"SYSTEM\CurrentControlSet\Control\Terminal Server\WinStations\RDP-Tcp"
generates an error stating “Absolute path information is required.”
What is the syntax to create the absolute path required?

The registry has a couple of root keys and all subkeys are relative to one of these.
In order to use the OpenSubKey method, you must have an instance of the RegistryKey method. To get an instance of RegistryKey, use one of the static members of the Registry class.
If for example you want the key HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet as seen in Regedit you would have to start with Registry.LocalMachine.
RegistryKey rk = Registry.LocalMachine.OpenSubKey(#"SYSTEM\CurrentControlSet");
... = rk.GetValue(...);
If you already have a key, yourkey.Name is the path of the key.

Related

Registry get directory owner programmatically using C#

I want to read programmatically the owner of a directory (and its subdirectories) of the windows registry using C#.
For example, assume my registry contains the directory HKEY_CURRENT_USER\Software\Microsoft which is owned by the user SYSTEM. A code example (leaving out the recursion over sub-directories of dir) how I intend to use it would be:
string dir = #"HKEY_CURRENT_USER\Software\Microsoft";
string owner = ReadRegOwner(dir); // owner is "SYSTEM"
However, I am not sure how to implement ReadRegOwner in C#. I have already found the RegistrySecurity class, but I am not sure how to use it to get the owner of a registry directory. It has the GetOwner member function, but that function requires an argument of type Type and I am not sure what to pass there.
Does anyone know how to implement this?
So, an implementation could look like:
string ReadRegOwner(string dir)
{
RegistryKey key = Registry.CurrentUser.OpenSubKey(dir, false);
RegistrySecurity rs = key.GetAccessControl();
IdentityReference owner = rs.GetOwner(typeof(System.Security.Principal.NTAccount));
return owner.ToString();
}
Example:
string dir = #"Software\Microsoft";
string owner = ReadRegOwner(dir); // Looks in HKEY_CURRENT_USER
Of course, CurrentUser could be also replaced if a different base key than HKEY_CURRENT_USER is desired.

CreateSubKey is not creating entry in current user

I am trying to create a sub key under Current user, Application runs successfully, but unable to create sub key under current user. Following is my application logic. Can any one tell me what mistake I am doing here?
RegistryKey myAppSettings = Registry.CurrentUser.CreateSubKey(#"SOFTWARE\MyAppSettings");
Console.WriteLine(myAppSettings);
//storing the values
myAppSettings.SetValue("appName", "C# Tutorials");
myAppSettings.SetValue("Demo", "Registry keys storage");
myAppSettings.Close();
CreateSubkey does not work with path values. You have to open the RegistryKey "software" and create the subkey for it.

Accessing all the keys under classesroot from registry with c#

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.

Using OpenSubKey not finding node that exists

I am using the cookie cutter code to get a registry key object in C#:
RegistryKey reg = Registry.LocalMachine.OpenSubKey("SOFTWARE\\MyNewKeyName\\");
After I run this code reg = null. However, if I switch the value passed to OpenSubKey to be any value in the registry under SOFTWARE that has additional nodes below it reg will now have a value. I've tried multiple keys with this pattern and it works. If I put any any key name that does not have additional child nodes it does not work. Ultimately I'm trying to read a string value inside of MyNewKeyName.
Why does my code not work and reg get populated if my key does not have any additional nodes below it?
Well it turns out that the values in the '32-bit' registry and the '64-bit' registry are not identical. So when viewing the registry via 'regedit' and seeing everything, programatically you may not and that's the issue I was running into. I noticed this by running GetSubKeyNames() and inspecting the keys returned. The quick answer is to check both versions of the registry to find the value sought:
//Check the 64-bit registry for "HKEY_LOCAL_MACHINE\SOFTWARE" 1st:
RegistryKey localMachineRegistry64 = RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, RegistryView.Registry64);
RegistryKey reg64 = localMachineRegistry64.OpenSubKey(registryKeyLocation, false);
if (reg64 != null)
{
return reg64.GetValue(registryKeyName, true).ToString();
}
//Check the 32-bit registry for "HKEY_LOCAL_MACHINE\SOFTWARE" if not found in the 64-bit registry:
RegistryKey localMachineRegistry32 = RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, RegistryView.Registry32);
RegistryKey reg32 = localMachineRegistry32.OpenSubKey(registryKeyLocation, false);
if (reg32 != null)
{
return reg32.GetValue(registryKeyName, true).ToString();
}
I think the problem is you are compiling it as x86 instead of compiling it as an x64 application. Follow the below steps:
Right click on Project
Select Properties
Select the Build tab
Change "Platform Target" to "x64"
Now run the project.

Writing to registry in a C# application

I'm trying to write to the registry using my C# app.
I'm using the answer given here: Writing values to the registry with C#
However for some reason the key isn't added to the registry.
I'm using the following code:
string Timestamp = DateTime.Now.ToString("dd-MM-yyyy");
string key = "HKEY_LOCAL_MACHINE\\SOFTWARE\\"+Application.ProductName+"\\"+Application.ProductVersion;
string valueName = "Trial Period";
Microsoft.Win32.Registry.SetValue(key, valueName, Timestamp, Microsoft.Win32.RegistryValueKind.String);
The Application.name and Application.version 'folders' don't exists yet.
Do I have to create them first?
Also, I'm testing it on a 64b Win version so I think if I want to check the registry for the key added I have to specifically check the 32bit registry in: C:\Windows\SysWOW64\regedit.exe don't I?
First of all if you want to edit key under LocalMachine you must run your application under admin rights (better use CurrentUser it's safer or create the key in installer). You have to open key in edit mode too (OpenSubKey method) to add new subkeys. I've checked the code and it works. Here is the code.
RegistryKey key = Registry.LocalMachine.OpenSubKey("Software",true);
key.CreateSubKey("AppName");
key = key.OpenSubKey("AppName", true);
key.CreateSubKey("AppVersion");
key = key.OpenSubKey("AppVersion", true);
key.SetValue("yourkey", "yourvalue");
You can use the following code to create and open the required registry keys.
RegistryKey SoftwareKey = Registry.LocalMachine.OpenSubKey("Software",true);
RegistryKey AppNameKey = SoftwareKey.CreateSubKey("AppName");
RegistryKey AppVersionKey = AppNameKey.CreateSubKey("AppVersion");
AppVersionKey.SetValue("yourkey", "yourvalue");
You can basically use CreateSubKey for all your application settings, as it will open the key for write access, if it already exists, and create it otherwise. There is no need to create first, and then open. OpenSubKey comes in handy when you are absolutely certain the key already exists, like in this case, with "HKEY_LOCAL_MACHINE\SOFTWARE\"
Also check if your registry calls are getting virtualised. See here for more information.
It can happen if your application is not UAC aware and occurs for compatibility reasons.
Real path
HKEY_LOCAL_MACHINE\Software\FooKey
Virtual path
HKEY_USERS\<User SID>_Classes\VirtualStore\Machine\Software\FooKey
Try to open HKLM\Software first. Then create key for your program, and then create key for version. Howewer, your key could be placed at HKLM\software\WOW6432Node. Check this.
The problem is you don't have enough privileges. Here is a way that works for my:
RegistryKey myKey = RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, RegistryView.Registry64);
myKey = myKey.OpenSubKey(subkey, RegistryKeyPermissionCheck.ReadWriteSubTree, RegistryRights.FullControl);
if (myKey != null)
{
myKey.SetValue("DefaultPrinterId", ldiPrinters[e.RowIndex].id, RegistryValueKind.String);
myKey.Close();
}
With RegistryKey.OpenBaseKey you open the correct registry, because when you don't have permissions the registry that you write, it does in another location.
By default, your changes will be written to HKLM\SOFTWARE\WOW6432Node\... because of registry redirection. This can be quite confusing.
In order to write to HKLM\SOFTWARE\..., you need to use RegistryKey.OpenBaseKey to open the 64-bit registry:
var path = #"SOFTWARE\...";
var baseKey = RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, RegistryView.Registry64);
var key = baseKey.CreateSubKey(path, RegistryKeyPermissionCheck.ReadWriteSubTree);
key.SetValue(name, value, RegistryValueKind.String);
Also, you need to have permission to write to the specified registry key.
You can get permission either by assigning permissions to specific users or service accounts or by running your app in elevated mode.

Categories

Resources