Registry In's and Out's Using C#

This is an article on using the Registry in C#. Having been looking around the web and on the MSDN libraries, I have determined that there is not a complete guide on using all the registry tools accessible using C#. So this article is going to cover all methods exposed to the user when developing in C#. Firstly i would like to say that I am very aware that the current consensus is that we should not be using the Registry to hold information about our programs anymore and that the ".NET" way is to store information in XML files. Well if that is you then you don't really need this article, however if you are accessing information from the registry then this is the source for you, please note that i have also included information from my previous article on "Advance Registry Access in C#". Ok so lets get down to business.

When using the .NET framework in C# the user needs to add access to the Microsoft.Win32 namespace in order to access registry manipulation tools, this is done as shown in the below code:

using Microsoft.Win32;

Once this reference has been added along with the other, it gives us access to the elements involved within registry control. There are two main classes associated with this namespace, RegistryKey and Registry. These classes are used together to allow us to do pretty much everything in the registry.

Registry Class
The Registry Class itself on its own doesn't do a lot for us this is because the Registry Class merely represents the seven top-level nodes within the registry for us to access and manipulate. The Registry class is powerful when used with the RegistryKey class. However if you open up Visual Studio.NET and add the namespace above and then just type, "Registry." you will see the list of the seven subnodes (Shown below).

Registry Class name
Registry Value
What is does
Registry.ClassesRoot HKEY_CLASSES_ROOT Responsible for telling the shell how to handle different file formats
Registry.CurrentConfig HKEY_CURRENT_CONFIG Represents the current session configuration
Registry.CurrentUser HKEY_CURRENT_USER Represents the profile of the current user
Registry.DynData HKEY_DYN_DATA Contains configuration data about dynamic data (i.e. in RAM)
Registry.LocalMachine HKEY_LOCAL_MACHINE Contains the System Information (i.e. Hardware)
Registry.PerformanceData HKEY_PERFORMANCE_DATA Contain information about the performance of applications
Registry.Users HKEY_USERS A repository for information regarding users and their preferences.

Now the we have identified what the Registry Class does and represents we can look at it's partner the RegistryKey Class.

RegistryKeyClass
The RegistryKey classis the most important part in terms of registry manipulation when using C#. TheRegistryKey class has many methods which the use can exploit to create and deletedata. Before we can do any of this we have to create an Instance of a RegistryKey, this is done using the code below:

RegistryKey OurKey = Registry.Users;

In the above code extract we have created a instance of RegistryKey called OurKey, we have initialized this key to be the HKEY_USERS subkey in the registry. Basically this mean that any method we use in this key will effect the direct subkeys of HKEY_USERS and their data items.

OpenSubKey()

OpenSubkey is a very important method when using the RegistryKey class, because it allows us to access/manipulate the subkey of the top key. This may

sound a
tad strange, basically if as above we have "OurKey" set to the HKEY_USERS key, using the OpenSubKey method we can set "OurKey" to a subkey of HKEY_USERS. The best we to demonstrate this is to show you some code (See below).

RegistryKey OurKey = Registry.Users;
OurKey = OurKey.OpenSubKey(".DEFAULT",true);


In the above code sample we have created our instance of the RegistryKey class and given it the value of the HKEY_USERS key. The next step is that we have opened a subkey within HKEY_USERS called ".DEFAULT", we should also note that it doesn't have to be a top level subnode either, We could have opened ".DEFAULT\subkey". The second part to the method is defining if the key is opened and Read-only mode or Read/Write mode. If the value is true we can edit items within the key, and the key itself.

DeleteSubKey()/ CreateSubKey() & DeleteSubKeyTree()

All these three methods are to do with the management of Subkeys under the current selected key. These methods are pretty self explanatory and the below code shows there implementation.

RegistryKey OurKey = Registry.Users; // Create OurKey set to HKEY_USERS
OurKey = OurKey.OpenSubKey(".DEFAULT",true); // Set it to HKEY_USERS\.DEFUALT
OurKey.CreateSubKey("OurSubKey"); // Create the key HKEY_USERS\.DEAFULT\OurSubKey
OurKey.CreateSubKey(@"OurSubKey\Subkey"); // Create a sub key HKEY_USERS\.DEFAULT\OurSubKey\Subkey
OurKey.DeleteSubKey(@"OurSubKey\SubKey"); // Delete the subkey name "subkey"
OurKey.DeleteSubKeyTree("OurSubKey"); // Delete the whole subkey and any subkeys below it

GetSubKeyNames()

GetSubKeyNames is an important method because it allows us to get all the names of the secondary subkeys, For instance we could get all the names of the subkeys below "HKEY_USERS". The only draw back being that it only gets the immediate subkey names. However with a little recursion we can get them all, the first code snippet is of the basic use of GetSubKeyNames().

//The first example shows it using a foreach loop to display each subkeyname
foreach
(string Keyname in OurKey.GetSubKeyNames())
{
 MessageBox.Show(Keyname);
}
//The second example shows how to tranfer the names into a string array
string[] Keynames = OurKey.GetSubKeyNames();

In the next snippet of code we see how we can use recursion to obtain all the names of the subkeys.

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);

GetValue()/ GetValuesNames()

These methods are also very important when you want to extract information form the registry, when you used the other methods to get to the subkey that you want you would like to extract the information from them. The first methods, GetValue allows you obtain the value held in a registry value by specifying its name, For example in our "test" subkey used earlier, i have a string (REG_SZ) value named "Testvalue" with the value "This is a test". To extract the value i would use the below code.

RegistryKey OurKey = Registry.Users;
OurKey = OurKey.OpenSubKey(@".DEFAULT\test",true);
MessageBox.Show(OurKey.GetValue("Testvalue").ToString());

As you will have noticed when we get information out of the registry we are always converting it using the ToString() method, this is because values and subkeys within the registry are classed as object and must therefore be converted, either via the ToString() method or by Casting.

As we have seen using the GetSubKeyNames() method we get the collection of names returned, this is also the case when we use the GetValueNames() methods. Using the code similar to the code used earlier we can obtain the names of the values, and also their values at the same time, as shown below.

RegistryKey OurKey = Registry.Users;
OurKey = OurKey.OpenSubKey(@".DEFAULT\test",

pan style="color:#0000ff;">true);
foreach(string valuename in OurKey.GetValueNames())
{
MessageBox.Show(valuename + " " + OurKey.GetValue(valuename).ToString());
}

SetValue()

The SetValue method does exactly what it says, it sets the value of a registry value, to use the function you supply the name of the value and what you want to set it to, if the value doesn't exist it creates it, simple as that, see the code below:

RegistryKey OurKey = Registry.Users;
OurKey = OurKey.OpenSubKey(@".DEFAULT\test",true);
OurKey.SetValue("Testvalue",0);

Using the SubKeyCount and Valuecount properties

You can use these two properties to obtain firstly of how many subkeys there directly below the specified key, and also the number of values under the specified key. to help understand we can look at the below code:

RegistryKey OurKey = Registry.Users;
OurKey = OurKey.OpenSubKey(@".DEFAULT\test",true);
MessageBox.Show(OurKey.SubKeyCount.ToString());
MessageBox.Show(OurKey.ValueCount.ToString());

Closing What we've worked on

I should also mention that when you have finished working and using a section of registry it makes good error free practice to close the key you have been using, this is done via the Close() method. See code below.

RegistryKey OurKey = Registry.Users;
OurKey.Close()

Unsupported Registry Functions
The.NET Framework supports a lot and in C# the RegistryKey class is very powerfuland can be used well to manipulate the registry. Most of the Win32 APIs which we would have had to use previously have been built in however there are a few that are not, and this is where i refer to my Article "Advance Registry Work in C#". These are RegLoadKey() and RegUnloadKey(). These two calls allow you to load registry Hives into the registry and then manipulate them. As you will have seen in that article you need to declare these calls and you also need to gain relevant privileges to use them.API's Declared

[StructLayout(LayoutKind.Sequential)]
public struct LUID
{
public int LowPart;
public int HighPart;
}
[StructLayout(LayoutKind.Sequential)]
public struct TOKEN_PRIVILEGES
{
public LUID Luid;
public int Attributes;
public int PrivilegeCount;
}

[DllImport("advapi32.dll", CharSet=CharSet.Auto)]
public static extern int OpenProcessToken(int ProcessHandle, int DesiredAccess,
ref int tokenhandle);

[DllImport("kernel32.dll", CharSet=CharSet.Auto)]
public static extern int GetCurrentProcess();

[DllImport("advapi32.dll", CharSet=CharSet.Auto)]
public static extern int LookupPrivilegeValue(string lpsystemname, string lpname,
[MarshalAs(UnmanagedType.Struct)] ref LUID lpLuid);

[DllImport("advapi32.dll", CharSet=CharSet.Auto)]
public static extern int AdjustTokenPrivileges(int tokenhandle, int disableprivs,
[MarshalAs(UnmanagedType.Struct)]ref TOKEN_PRIVILEGES Newstate, int bufferlength,
int PreivousState, int Returnlength);

[DllImport("advapi32.dll", CharSet=CharSet.Auto, SetLastError=true)]
public static extern int RegLoadKey(uint hKey,string lpSubKey, string lpFile);

[DllImport("advapi32.dll", CharSet=CharSet.Auto, SetLastError=true)]
public static extern int RegUnLoadKey(uint hKey, string lpSubKey);

public const int TOKEN_ADJUST_PRIVILEGES = 0×00000020;
public const int TOKEN_QUERY = 0×00000008;
public const int SE_PRIVILEGE_ENABLED = 0×00000002;
public const string SE_RESTORE_NAME = "SeRestorePrivilege";
public const string SE_BACKUP_NAME = "SeBackupPrivilege";
public const uint HKEY_USERS = 0×80000003;
public string shortname;
bool unloaded = false;

API's Used

int token=0;
int retval=0;

TOKEN_PRIVILEGES TP = new TOKEN_PRIVILEGES();
TOKEN_PRIVILEGES TP2 = new TOKEN_PRIVILEGES();
LUID RestoreLuid = new LUID();
LUID BackupLuid = new LUID();

retval = OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, ref token);
retval = LookupPrivilegeValue(null, SE_RESTORE_NAME, ref RestoreLuid);
retval = LookupPrivilegeValue(null, SE_BACKUP_NAME, ref BackupLuid);
TP.PrivilegeCount = 1;
TP.Attributes = SE_PRIVILEGE_ENABLED;
TP.Luid = RestoreLuid;
TP2.PrivilegeCount = 1;
TP2.Attributes = SE_PRIVILEGE_ENABLED;
TP2.Luid = BackupLuid;

retval = AdjustTokenPrivileges(token, 0, ref TP, 1024, 0, 0);
retval = AdjustTokenPrivileges(token, 0, ref TP2, 1024, 0, 0);

// Loading a Hive "C:\NTUSER.DAT"

RegLoadKey(HKEY_USERS,"NTUSER.DAT",@"C:\NTUSER.DAT");)

// Unloading a Hive "C:\NTUSER.DAT"

RegUnLoadKey(HKEY_USERS,"NTUSER.DAT");

About the Author

My name is Michael Bright, I'm a university student studying a Bsc in Computer Science at University College Chester. I have a love for all thing computers and have only worked wit

h C# for about 3 months. I am currently training for my MCP in it. My other interests are C, VB, HTML, ASP and also Flash. I have interests in Developing Network app's and Network Security. My Web site is csharp.brightweb.co.uk where you can find examples of my Work, including my Defender Security applications.

Twitter Digg Delicious Stumbleupon Technorati Facebook Email

No comments yet... Be the first to leave a reply!