Introduction
Registry is one of the most important parts of the operating system, primarily because of the fact that it contains volumes of information regarding the operating system configuration, the hardware details, and software configuration details, amongst other things. And from the point of view of a developer, access to the registry in a programmatic fashion is even more important so that applications have access to all the system related details that they require, and also define their own behavior by storing their configuration in the registry.
Prior to .NET, access to registry was made using the Win32 Registry APIs, exported by the ADVAPI DLL. Under .NET, one can go about using the same set of APIs using Platform Invocation Services (PInvoke) since .NET is all about working with and executing managed code, i.e., code run under the supervision of the common language runtime (CLR), while the the Registry APIs exist in the non-managed (non-.NET) world. Coding definitely becomes inconvenient and terse. So, the better approach is to use the Microsoft.Win32
namespace present in the .NET class library.
In this article, I shall introduce you to the Microsoft.Win32
namespace's registry oriented classes, and how to use their methods to interact with the registry. In this process, we shall create a console .NET application, programmed using C#, that will assist us in installing and uninstalling application entries in the HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\Run
registry key. For those who don't know, applications pointed to by entries in this location run automatically (something like what AUTOEXEC.BAT did in the days of DOS) when a user logs on.
So, let's get started.
Hello Microsoft.Win32!
Microsoft.Win32
is one of the namespaces named after the company. In addition to supporting registry access, this namespace also supports working with various system related and power related event handling for the operating system. But of course, we focus our attention on registry access.
To work with the registry, the namespace provides two class: Registry
and RegistryKey
. Essentially, the Registry
class is sealed in nature and thus, cannot be inherited, with its main purpose being providing access to the root registry keys:
HKEY_LOCAL_MACHINE
HKEY_CLASSES_ROOT
HKEY_CURRENT_USER
HKEY_USERS
HKEY_CURRENT_CONFIG
HKEY_DYNAMIC_DATA
HKEY_PERFORMANCE_DATA
Of course, not all of these keys are present on all Windows operating systems. The Registry
class contains a static field for each of these classes, which is of the type RegistryKey
. For e.g., in the process of designing the application discussed earlier, we would need to get a reference to the HKEY_LOCAL_MACHINE
registry key. Hence, we use the following piece of code:
RegistryKey rkHKLM = Registry.LocalMachine;
Of course, we do supply a reference to the Microsoft.Win32
namespace before any code referencing the use of registry classes.
Talking with the registry
Once we get a reference to the required base registry key, we can use any one of the many methods and/or properties of the RegistryKey
class to interact with the registry. But before I move further, below is the listing of the code of our application, in reference to which we shall proceed to understand the protocol of interacting with the registry:
using System;
using Microsoft.Win32;
class CRegInstaller
{
public static void Main(string[] args)
{
Console.WriteLine("RegInstaller - by Kumar Gaurav Khanna");
Console.WriteLine("20th April, 2002");
Console.WriteLine("WWW: http://www.wintoolzone.com/");
Console.WriteLine("Email: gaurav@wintoolzone.com\n");
if (args.Length<3)
{
Console.WriteLine("Reginstaller <option> <entry name> <path>");
Console.WriteLine("where:");
Console.WriteLine("<option> = /I to install, /U to uninstall");
Console.WriteLine("<path> = fully qualified path to the application executable.");
Console.WriteLine("<entry name> = name for the entry in the registry.\n");
Console.WriteLine("When option is /U, <path> will be ignored.");
return;
}
RegistryKey rkHKLM = Registry.LocalMachine;
RegistryKey rkRun;
try
{
rkRun =
rkHKLM.OpenSubKey("Software\\Microsoft\\Windows\\CurrentVersion\\Run",true);
}
catch
{
Console.WriteLine("Unable to open the RUN subkey!");
rkHKLM.Close();
return;
}
if (args[0].ToLower()=="/i")
{
try
{
rkRun.SetValue(args[1],args[2]);
Console.WriteLine("Entry successfully created in the registry!");
}
catch
{
Console.WriteLine("Unable to create an entry for the application!");
}
}
else if (args[0].ToLower()=="/u")
{
try
{
rkRun.DeleteValue(args[1]);
Console.WriteLine("Entry successfully deleted from the registry!");
}
catch
{
Console.WriteLine("Unable to delete applications' entry!");
}
}
else
Console.WriteLine("Invalid command line switch: {0}",args[0]);
rkRun.Close();
rkHKLM.Close();
}
}
Let's dissect and understand the source code. We start off by referencing the required namespaces. This is followed by displaying of the application name, subsequent to which we check the number of command-line arguments passed to our application. These arguments specify if the application would be creating an entry for an application in the HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\Run
registry key, or deleting its entry from there. The first parameter is /I
to create an entry, or /U
to remove an entry. The name of the entry is the second parameter, while the application pointed to by the entry is the third parameter. The third parameter is ignored by the application if it is deleting its entry, since we just need the entry name for the deletion.
Once all the checks have been made, we proceed to get a reference to the HKEY_LOCAL_MACHINE
registry key. This reference is actually RegistryKey
type, and we use its OpenSubkey
method to attempt to open the Software\Microsoft\Windows\CurrentVersion\Run
subkey in a try
block. This method has two overloaded versions: one that opens the subkey in the read-only mode, and the second one which specifies if we wish to open it in write-access mode. I have used the second method, in which the first parameter is the subkey to be opened, and the second parameter is a boolean value, which if set to true
, opens the subkey in a write-access mode.
Once that is done, if an error occurs during the opening of the subkey, an exception will be thrown. We aren't interested in the exact nature of the exception, so I have used a generic "catch-all" catch
block, which displays the error message and closes the HKEY_LOCAL_MACHINE
subkey using the Close
method of the RegistryKey
class.
If, however, the subkey is opened successfully, we store the reference to the same, and proceed to determine the nature of our work, i.e., whether to create an entry or delete it. To create an entry in the subkey, we call the SetValue
method of the RegistryKey
class. The first parameter of this method is the name of the entry that will be created, and the second parameter is the value of the entry, which in this case is the path to the application to be auto-executed.
Likewise, to delete an entry, a call is made to the DeleteValue
method of the RegistryKey
class, which takes just one parameter: the name of the entry to be deleted. If any error occurs during the creation or the deletion of the entry, an exception will be thrown, which the code catches using the generic "catch-all" block. Appropriate messages are then displayed.
Once everything is done, we finally close the registry keys in the reverse order in which they were opened.
That is all there is to have a basic to-fro interaction with the registry. Of course, I haven't covered all the methods and properties, but their usage is quite intuitive. But the point is the ease with which we could interact with the registry. If you have ever programmed for the registry using the Win32 Registry APIs, you will definitely see the difference between the approach of .NET and that of the Win32 APIs, and will surely agree that the .NET class has made things very simple to work with.
I hold Early Acheiver in MCSE 2000, MCSE NT 4.0, MCP+I, and actively involved in programming using C/C++, .NET framework, C#, Win32 API, VB, ASP and MFC.
I also have various publications to my credit at MSDN Online Peer Journal, Windows Developer Journal (http://www.wdj.com/), Developer 2.0 (http://www.developer2.com/), and PC Quest (http://www.pcquest.com/).