C#: Find a key without knowing where it is - c#

I'd like to preface this by highlighting that I am fairly new to C#.
I'm trying to make a program to find and edit a registry value in order to disable CPU core parking using this method: Registry Edit
The issue is that I know the start of the key:
HKEY_LOCAL_MACHINE\SYSTEM\ControlSet001\Control\Power\PowerSettings\
But not the Next part but I know the segment after that:
0cc5b647-c1df-4637-891a-dec35c318583
So if it looks like this:
HKEY_LOCAL_MACHINE\SYSTEM\ControlSet001\Control\Power\PowerSettings\<UNKNOWN>\0cc5b647-c1df-4637-891a-dec35c318583
How do I find the using Registry and Registrykey? I tried looping through all subkeys and I just get an exception because all I get back is null.
Any suggestions appreciated.

You can use recursion for finding SubKey.
private RegistryKey SearchSubKey(RegistryKey Key,String KeyName)
{
foreach (String subKey in Key.GetSubKeyNames())
{
RegistryKey key1 = Key.OpenSubKey( subKey);
if (subKey.ToUpper() == KeyName.ToUpper())
return key1;
else
{
RegistryKey mReturn = SearchSubKey(key1, KeyName);
if (mReturn != null)
return mReturn;
}
}
return null;
}
Call this function as
RegistryKey key = Registry.LocalMachine.OpenSubKey(#"SYSTEM\ControlSet001\Control\Power\PowerSettings\");
RegistryKey SubKey = SearchSubKey(key, "0cc5b647-c1df-4637-891a-dec35c318583");
This function search through all sub keys in main key recursively. If you want to search up to particular level then you have to add that logic in function.

I guess you forgot to mention the Registry key name in a proper fashion. Here is the piece of code which brings out the output :
class Program
{
static void Main(string[] args)
{
RegistryKey key = Registry.LocalMachine.OpenSubKey("Software\\Microsoft\\Windows\\CurrentVersion");
foreach (var v in key.GetSubKeyNames())
{
RegistryKey key1 = Registry.LocalMachine.OpenSubKey("Software\\Microsoft\\Windows\\CurrentVersion\\" + v);
foreach ( var v1 in key1.GetSubKeyNames())
{
if (v1 == "{00EC8ABC-3C5A-40F8-A8CB-E7DCD5ABFA05}")
Console.WriteLine(key1);
}
}
}
}
Please let me know if this works.

Related

Deleting a registry key

I am trying to delete a registry key sub tree which happens to be SAPI 5 user profile as shown below. The "nameofprofile" is the data value of the subkey and the subkey name is a CLSID but it comes up with an exception telling me that the subkey does not exist?
RegistryKey RegKey = Registry.CurrentUser.OpenSubKey("Software\\Microsoft\\Speech\\RecoProfiles\\Tokens\\", true);
RegKey.DeleteSubKeyTree("NameOfProfile");
You can try this.
string keyName = #"Software\Microsoft\Speech\RecoProfiles\Tokens";
using (RegistryKey key = Registry.CurrentUser.OpenSubKey(keyName, true))
{
key.DeleteSubKeyTree("NameOfProfile",false);
}
If you get the error again, you can try to run application in administrator mode.
Do a search of the string[] GetSubKeyNames() first and see if the sub key exists.
Try ignoring casing in case that is an issue.
var name = #"Software\Microsoft\Speech\RecoProfiles\Tokens";
var regKey = Registry.CurrentUser.OpenSubKey(name, true);
if (regKey != null) {
using (regKey) {
var subKeyName = "CLSID";
var actual = regKey.GetSubKeyNames()
.FirstOrDefault(n => string.Equals(n, subKeyName, StringComparison.InvariantCultureIgnoreCase));
if (actual != null) {
regKey.DeleteSubKeyTree(actual);
}
}
}
In the end I worked it out myself and I did this which worked fine. I should have said in the post that I always knew the profile name but I did not know the CLSID. No doubt there is an easier way to do this(No special permissions were required which was preferable if possible):
public static void DeleteKey (String profileName)
{
// Folder for SAPI 5 user profile tokens
String keyLocation = #"Software\Microsoft\Speech\RecoProfiles\Tokens";
RegistryKey key = Registry.CurrentUser.OpenSubKey(keyLocation, true);
// Get a list of Key names and work out which one is the "test" profile
String [] subKeyNames = key.GetSubKeyNames();
// Enumerate through the sub key names to find out which one is the "Test" profile
for(int i = 0; i < subKeyNames.Length; i++)
{
RegistryKey subKey =
Registry.CurrentUser.OpenSubKey("Software\\Microsoft\\Speech\\RecoProfiles\\Tokens\\" + subKeyNames[i]);
if(((String)subKey.GetValue("")).Equals(profileName))
{
key.DeleteSubKeyTree(subKeyNames[i]);
return;
}
}
}

Passing path to RegistryKey but getting back different path instead

Using RegistryKey in C# I'm trying to find a specific software in:
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall
But even though I pass this path to SubKey, I get back this path instead:
HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall
Code:
public void GetSubKeys(RegistryKey SubKey)
{
List<string> viList = new List<string>();
string[] val = SubKey.GetSubKeyNames();
foreach (var VARIABLE in val)
{
RegistryKey SubKey1 = SubKey.OpenSubKey(SubKey + #"\" + VARIABLE);
if (SubKey1.ToString().Contains("MySw"))
{
viList.Add(VARIABLE);
}
}
}
I know that because I'm searching for a specific SW which is not located in the WOW6432Node registry key, but in the other key, and there are various sw which are shown in the WOW6432Node key and not in the first key...
How come?
Any ideas?

Printing entire tree contents of LocalMachine

I'm trying to develop a c# program to print the entire tree of LocalMachine to the console. So far I've just been able to get the subkeys of HKEY_LOCAL_MACHINE, but nothing deeper than that. I'm relatively sure I need to use some kind of recursion here to get all the contents of subkeys and their subkeys, and so on. I'm just not sure how to go about it. Here's what I've got as of now:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Win32;
namespace PrintLocalMachine
{
class PrintLocalMachine
{
static void Main(string[] args)
{
Console.Out.WriteLine(Registry.LocalMachine.Name);
string[] subkeynames = Registry.LocalMachine.GetSubKeyNames();
foreach (string subkey in subkeynames)
{
try
{
RegistryKey rk = Registry.LocalMachine.OpenSubKey(subkey);
Console.Out.WriteLine(rk.Name);
string[] subkeynames2 = rk.GetSubKeyNames();
foreach (string s in subkeynames2)
{
recurse(s, rk);
}
}
catch (Exception e) { }
}
}
private static void recurse(string sub, RegistryKey rk)
{
RegistryKey rk2 = Registry.LocalMachine.OpenSubKey(sub);
Console.Out.WriteLine(rk2.Name);
string[] subkeynames3 = rk.GetSubKeyNames();
foreach(string s2 in subkeynames3){
recurse(s2, rk2);
}
}
}
}
Could someone explain how I should go about this? I really just need to be pointed in the right direction, I've just hit a wall with this.
EDIT: I changed a bit and updated the code; the updated code is hanging on HKEY_CURRENT_MACHINE\SAM, just printing it over and over until StackOverflowException
recurse() is not recursion unless it calls itself.
Move all your code from main to recurse() and call recurse() from main.
You might also want to close opened subkeys.
You are right. This kind of problem where you have a structure inside a structure can be solved through recursion. What you need to do is write a recursive function i.e. a function that calls itself until a certain condition satisfies. In this case that condition would be that if a Registry Key has at least one child we need to go inside that Registry Key and we will continue to do so until we reach a leaf node i.e. a Registry Key which has no more children.
private static void Main(string[] args)
{
string[] subkeynames = Registry.LocalMachine.GetSubKeyNames();
Console.Out.WriteLine(Registry.LocalMachine.Name);
foreach (string subkey in subkeynames)
{
try
{
//this might raise a security exception
RegistryKey rk = Registry.LocalMachine.OpenSubKey(subkey);
recurse(rk);
rk.Close();
}
catch (Exception e)
{
Console.Write("Couldnt access key : " + subkey + "\n " + e.ToString());
}
}
Console.ReadKey();
}
private static void recurse(RegistryKey rk)
{
Console.WriteLine(rk.Name);
string[] subkeys = rk.GetSubKeyNames();
if (null != subkeys && subkeys.Count() > 0)
{
foreach (var subkey in subkeys)
{
try
{
//this might raise a security exception
RegistryKey key = rk.OpenSubKey(subkey);
recurse(key);
}
catch (Exception e)
{
Console.Write("Couldnt access key : " + subkey + "\n " + e.ToString());
}
}
}
}

get installed version of an application using c#

I would to get installed version of an application (say, MyApp) using C#.
I will do this much,
1. Create a 'Set Up' for MyApp of version 5.6
2. Install MyApp.
I will create another application (say VersionTracker)to get the version of installed applications. So if I pass the name 'MyApp' I would like to get the version as '5.6'. If another application say Adobe Reader is installed in my system, I want to get the version of Adobe Reader if I pass 'Adobe Reader'.
I need to know how to build 'VersionTracker'
The first and the most important thing is that not all applications do save their version somewhere in the system. To be honest, only a few of them do that. The place where you should look are the Windows Registry. Most of installed applications put their installation data into the following place:
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall
However, it's not that easy - on 64bit Windows, the 32bit (x86) applications save their installation data into another key, which is:
HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall
In these keys there are many keys, some of them have got "easy-readable" name, such as Google Chrome, some of them got names such as {63E5CDBF-8214-4F03-84F8-CD3CE48639AD}. You must parse all these keys into your application and start looking for the application names. There are usually in DisplayName value, but it's not always true. The version of the application is usually in DisplayVersion value, but some installers do use another values, such as Inno Setup: Setup Version, ... Some application do have their version written in their name, so it's possible that the application version is already in the DisplayName value.
Note: It's not easy to parse all these registry keys and values and to "pick" the correct values. Not all installers save the application data into these keys, some of them do not save the application version there, etcetera. However, it's usual that the application use these registry keys. [Source: StackOverflow: Detecting installed programs via registry, browsing my own registry]
Alright, so now when you know where you should look, you have to program it all in C#. I won't write the application for you, but I'll tell you what classes you should use and how to. First, you need these:
using System;
using Microsoft.Win32;
To get to your HKEY_LOCAL_MACHINE, create a RegistryKey like this:
RegistryKey baseRegistryKey = Registry.LocalMachine;
Now you need to define subkeys:
string subKey = "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall";
// or "SOFTWARE\\Wow6432Node\\Microsoft\\Windows\\CurrentVersion\\Uninstall"
Now you need to go to the subkey, so create a new RegistryKey:
RegistryKey uninstallKey = baseRegistryKey.OpenSubKey(subKey);
Now you need to go thru all the subkeys that are there, so first we get the names of all the subkeys:
string[] allApplications = uninstallKey.GetSubKeyNames();
Now you must go thru all the subkeys yourself, one by one, by creating a new registry key (you don't have to, but I'll do it):
RegistryKey appKey = baseRegistryKey.OpenSubKey(subKey + "\\" + applicationSubKeyName);
where applicationSubKeyName is the name of the subkey you're currently checking. I recommend foreach statement, which helps you (you must however have some experience with C# already, I'm not going to tell you how to use foreach here).
Now check the application's name and compare it with name of your desired application (you cannot rely on the subkey name, because, as I already said, they can be called for example {63E5CDBF-8214-4F03-84F8-CD3CE48639AD}, so you must check the name here):
string appName = (string)appKey.GetValue("DisplayName");
If it's the correct application (you must check it yourself), find the version:
string appVersion = (string)appKey.GetValue("DisplayVersion");
Et voilĂ , you have the version. At least there's like a 60 - 80% chance you have...
Remember! If some key or value doesn't exist, the method returns null. Remember to check if the returned value is null everytime, otherwise your application will crash.
Where to find more? The Code Project: Read, write and delete from registry with C#
I really hope I helped you. And if you wanted to know something else and I didn't understand your question, then, please, ask better next time. :)
///
/// Author : Muhammed Rauf K
/// Date : 03/07/2011
/// A Simple console application to create and display registry sub keys
///
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
// it's required for reading/writing into the registry:
using Microsoft.Win32;
namespace InstallationInfoConsole
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Registry Information ver 1.0");
Console.WriteLine("----------------------------");
Console.Write("Input application name to get the version info. (for example 'Nokia PC Suite'): ");
string nameToSearch = Console.ReadLine();
GetVersion(nameToSearch);
Console.WriteLine("----------------------------");
Console.ReadKey();
}
///
/// Author : Muhammed Rauf K
/// Date : 03/07/2011
/// Create registry items
///
static void Create()
{
try
{
Console.WriteLine("Creating registry...");
// Create a subkey named Test9999 under HKEY_CURRENT_USER.
string subKey;
Console.Write("Input registry sub key :");
subKey = Console.ReadLine();
RegistryKey testKey = Registry.CurrentUser.CreateSubKey(subKey);
Console.WriteLine("Created sub key {0}", subKey);
Console.WriteLine();
// Create two subkeys under HKEY_CURRENT_USER\Test9999. The
// keys are disposed when execution exits the using statement.
Console.Write("Input registry sub key 1:");
subKey = Console.ReadLine();
using (RegistryKey testKey1 = testKey.CreateSubKey(subKey))
{
testKey1.SetValue("name", "Justin");
}
}
catch (Exception e)
{
Console.WriteLine(e.Message);
}
}
static void GetVersion(string nameToSearch)
{
// Get HKEY_LOCAL_MACHINE
RegistryKey baseRegistryKey = Registry.LocalMachine;
// If 32-bit OS
string subKey
//= "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall";
// If 64-bit OS
= "SOFTWARE\\Wow6432Node\\Microsoft\\Windows\\CurrentVersion\\Uninstall";
RegistryKey unistallKey = baseRegistryKey.OpenSubKey(subKey);
string[] allApplications = unistallKey.GetSubKeyNames();
foreach (string s in allApplications)
{
RegistryKey appKey = baseRegistryKey.OpenSubKey(subKey + "\\" + s);
string appName = (string)appKey.GetValue("DisplayName");
if(appName==nameToSearch)
{
string appVersion = (string)appKey.GetValue("DisplayVersion");
Console.WriteLine("Name:{0}, Version{1}", appName, appVersion);
break;
}
}
}
static void ListAll()
{
// Get HKEY_LOCAL_MACHINE
RegistryKey baseRegistryKey = Registry.LocalMachine;
// If 32-bit OS
string subKey
//= "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall";
// If 64-bit OS
= "SOFTWARE\\Wow6432Node\\Microsoft\\Windows\\CurrentVersion\\Uninstall";
RegistryKey unistallKey = baseRegistryKey.OpenSubKey(subKey);
string[] allApplications = unistallKey.GetSubKeyNames();
foreach (string s in allApplications)
{
RegistryKey appKey = baseRegistryKey.OpenSubKey(subKey + "\\" + s);
string appName = (string)appKey.GetValue("DisplayName");
string appVersion = (string)appKey.GetValue("DisplayVersion");
Console.WriteLine("Name:{0}, Version{1}", appName, appVersion);
}
}
}
}
Next code base on similar solution is working for me:
var version = GetApplicationVersion("Windows Application Driver");
string GetApplicationVersion(string appName)
{
string displayName;
// search in: CurrentUser
var key = Registry.CurrentUser.OpenSubKey(#"SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall");
foreach (var keyName in key.GetSubKeyNames())
{
var subKey = key.OpenSubKey(keyName);
displayName = subKey.GetValue("DisplayName") as string;
if (appName.Equals(displayName, StringComparison.OrdinalIgnoreCase))
return subKey.GetValue("DisplayVersion").ToString();
}
// search in: LocalMachine_32
key = Registry.LocalMachine.OpenSubKey(#"SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall");
foreach (var keyName in key.GetSubKeyNames())
{
var subKey = key.OpenSubKey(keyName);
displayName = subKey.GetValue("DisplayName") as string;
if (appName.Equals(displayName, StringComparison.OrdinalIgnoreCase))
return subKey.GetValue("DisplayVersion").ToString();
}
// search in: LocalMachine_64
key = Registry.LocalMachine.OpenSubKey(#"SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall");
foreach (var keyName in key.GetSubKeyNames())
{
var subKey = key.OpenSubKey(keyName);
displayName = subKey.GetValue("DisplayName") as string;
if (appName.Equals(displayName, StringComparison.OrdinalIgnoreCase))
return subKey.GetValue("DisplayVersion").ToString();
}
// NOT FOUND
return null;
}

How do I iterate through registry keys using C#?

how can iterate through the registry using C#? I wish to create a structure for representing attributes of each key.
I think what you need is GetSubKeyNames() as in this example.
private void GetSubKeys(RegistryKey SubKey)
{
foreach(string sub in SubKey.GetSubKeyNames())
{
MessageBox.Show(sub);
RegistryKey local = Registry.Users;
local = SubKey.OpenSubKey(sub,true);
GetSubKeys(local); // By recalling itself it makes sure it get all the subkey names
}
}
//This is how we call the recursive function GetSubKeys
RegistryKey OurKey = Registry.Users;
OurKey = OurKey.OpenSubKey(#".DEFAULT\test",true);
GetSubKeys(OurKey);
(NOTE: This was original copied from a tutorial http://www.csharphelp.com/2007/01/registry-ins-and-outs-using-c/, but the site now appears to be down).
private void GetSubKeys(RegistryKey SubKey)
{
foreach(string sub in SubKey.GetSubKeyNames())
{
MessageBox.Show(sub);
RegistryKey local = Registry.Users;
local = SubKey.OpenSubKey(sub,true);
GetSubKeys(local); // By recalling itselfit makes sure it get all the subkey names
}
}
//This is how we call the recursive function GetSubKeys
RegistryKey OurKey = Registry.Users;
OurKey = OurKey.OpenSubKey(#".DEFAULT\test",true);
GetSubKeys(OurKey);
http://www.csharphelp.com/2007/01/registry-ins-and-outs-using-c/
You can use Microsoft.Win32.RegistryKey and the GetSubKeyNames method as described here:
http://msdn.microsoft.com/en-us/library/microsoft.win32.registrykey_members%28v=VS.100%29.aspx
Be aware though that this might be very slow if you're iterating through a large part of the registry.
Check out the RegistryKey.GetSubKeyNames method.
This function will retrieve the name of all subkeys and you can iterate through them and do whatever you wish.

Categories

Resources