Registry Review
and Registry Classes in .Net
The
Registry is a special database used to store settings and configurations for
the 32 bit versions of Microsoft Windows including Windows 95, 98, ME and
NT/2000. It contains information and settings for all the hardware, software,
users, and preferences of the PC. In addition, it is an important information
repository for COM components. Whenever a user makes changes to a Control Panel
settings, or File Associations, System Policies, or installed software, the
changes are reflected and stored in the Registry.
The
physical files that make up the registry are stored differently depending on
your version of Windows; under Windows 95 and 98, it is contained in two hidden
files in your Windows directory, called USER.DAT and SYSTEM.DAT,
for Windows Me there is an additional CLASSES.DAT file, while under
Windows NT/2000 the files are contained separately in the
%SystemRoot%\System32\Config directory. You cannot edit these files directly,
you must use a tool commonly known as a "Registry Editor"
(regedit.exe or regedt32.exe) to make any changes.
The
Registry has a hierarchal structure, although it looks complicated the
structure is similar to the directory structure on your hard disk, with Regedit
being similar to Windows Explorer.
|
Each
main branch (denoted by a folder icon in the Registry Editor, see left) is
called a Hive, and Hives contains Keys. Each key can contain
other keys (sometimes referred to as sub-keys), as well as Values. The
values contain the actual information stored in the Registry. There are three
types of values; String, Binary, and DWORD - the use of
these depends upon the context. |
There are seven main
hives in the Registry (although only five are visible through regedit), each
containing a specific portion of the information stored in the Registry. They
are as follows:
The following two hives contain dynamic data
which changes frequently.
Each registry value is
stored as one of five main data types:
Other data types not
available through the standard registry editors include:
The Registry Editor
(REGEDIT.EXE) is included with most version of Windows (although you won't find
it on the Start Menu) it enables you to view, search and edit the data within
the Registry. There are several methods for starting the Registry Editor, the
simplest is to click on the Start button, then select Run, and in
the Open box type "regedit", and if the Registry Editor is
installed it should now open and look like the image below.
An alternative Registry
Editor (REGEDT32.EXE) is available for use with Windows NT/2000, it includes
some additional features not found in the standard version, including; the
ability to view and modify security permissions, and being able to create and
modify the extended string values REG_EXPAND_SZ & REG_MULTI_SZ.
Create a Shortcut to
Regedit
This
can be done by simply right-clicking on a blank area of your desktop, selecting
New, then Shortcut, then in the Command line box enter "regedit.exe"
and click Next, enter a friendly name (e.g. 'Registry Editor') then click
Finish and now you can double click on the new icon to launch the Registry
Editor.
Using Regedit to
Examine Attributes of a Software Installed on Your Machine
As an example, one of the applications installed on my
machine is called an HRMS application made by Best Software. The HRMS
application settings are stored under the Best Software key in the HKLM hive.
By running regedit and expanding on the HKEY_LOCAL_MACHINE, then expanding on
Software and the Best Software key, the following information is
contained in the registery.
Majority of the
Microsoft made products are installed under the key Microsoft under Software in
HKLM.
For example, if you
have the SQL server installed, then you can look up some of the registery entries
for it by examining the MSSQLServer key in the Software section in the HKLM
hive. On my machine, this looks as:
Using Regedit to modify
your Registry
Once
you have started the Regedit you will notice that on the left side there is a
tree with folders, and on the right the contents (values) of the currently
selected folder.
Like Windows explorer,
to expand a certain branch (see the structure of the registry section), click
on the plus sign [+] to the left of any folder, or just double-click on the
folder. To display the contents of a key (folder), just click the desired key,
and look at the values listed on the right side. You can add a new key or value
by selecting New from the Edit menu, or by right-clicking your mouse. And you
can rename any value and almost any key with the same method used to rename
files; right-click on an object and click rename, or click on it twice
(slowly), or just press F2 on the keyboard. Lastly, you can delete a key or
value by clicking on it, and pressing Delete on the keyboard, or by
right-clicking on it, and choosing Delete.
Note:
it is always a good idea to backup your registry before making any changes to
it. It can be intimidating to a new user, and there is always the possibility
of changing or deleting a critical setting causing you to have to reinstall the
whole operating system. It's much better to be safe than sorry!
A great feature of the
Registry Editor is it's ability to import and export registry settings to a
text file, this text file, identified by the .REG extension, can then be saved
or shared with other people to easily modify local registry settings. You can
see the layout of these text files by simply exporting a key to a file and
opening it in Notepad, to do this using the Registry Editor select a key, then
from the "Registry" menu choose "Export Registry File...",
choose a filename and save. If you open this file in notepad you will see a
file similar to the example below:
REGEDIT4
[HKEY_LOCAL_MACHINE\SYSTEM\Setup]
"SetupType"=dword:00000000
"CmdLine"="setup -newsetup"
"SystemPrefix"=hex:c5,0b,00,00,00,40,36,02
The layout is quite
simple, REGEDIT4 indicated the file type and version, [HKEY_LOCAL_MACHINE\SYSTEM\Setup]
indicated the key the values are from, "SetupType"=dword:00000000
are the values themselves the portion after the "=" will vary
depending on the type of value they are; DWORD, String or Binary.
So by simply editing
this file to make the changes you want, it can then be easily distributed and
all that need to be done is to double-click, or choose "Import" from
the Registry menu, for the settings to be added to the system Registry.
Example:
From the Edit->Find menu in
regedit, search for:swflash.ocx (this is the flash ActiveX control). Then click
on the corresponding CLSID key as shown below.
Then choose
Registery->Export Registery File. Specify a file name of flash.reg in a temp
folder. You will see the following contents of the file (you can examine it
through notepad).
Windows Registry Editor Version 5.00
[HKEY_CLASSES_ROOT\CLSID\{1171A62F-05D2-11D1-83FC-00A0C9089C5A}]
@="FlashProp Class"
[HKEY_CLASSES_ROOT\CLSID\{1171A62F-05D2-11D1-83FC-00A0C9089C5A}\InprocServer32]
@="C:\\WINNT\\System32\\macromed\\flash\\swflash.ocx"
"ThreadingModel"="Apartment"
[HKEY_CLASSES_ROOT\CLSID\{1171A62F-05D2-11D1-83FC-00A0C9089C5A}\Programmable]
Deleting keys or values
using a REG file
It
is also possible to delete keys and values using REG files. To delete a key
start by using the same format as the REG file above, but place a "-"
symbol in front of the key name you want to delete. For example to delete the
[HKEY_LOCAL_MACHINE\SYSTEM\Setup] key the reg file would look like this:
REGEDIT4
[-HKEY_LOCAL_MACHINE\SYSTEM\Setup]
The format used to delete
individual values is similar, but instead of a minus sign in front of the whole
key, place it after the equal sign of the value. For example, to delete the
value "SetupType" the file would look like:
REGEDIT4
[HKEY_LOCAL_MACHINE\SYSTEM\Setup]
"SetupType"=-
Use this feature with
care, as deleting the wrong key or value could cause major problems within the
registry, so remember to always make a backup first.
Regedit Command Line
Options
Regedit
has a number of command line options to help automate it's use in either batch
files or from the command prompt. Listed below are some of the options, please
note the some of the functions are operating system specific.
regedit.exe [options] [filename]
filename Imports .reg file into the registry
/s Silent, i.e. hide confirmation box when importing files
/e Export registry file
e.g. regedit /e file.reg HKEY_USERS\.DEFAULT
/L:system Specify the location of the system.dat to use
/R:user Specify the location of the user.dat to use
/C Compress [filename] (Windows 98)
Backup and Restore the
Registry
Windows 95
Microsoft
included a utility on the Windows 95 CD-ROM that lets you create backups of the
Registry on your computer. The Microsoft Configuration Backup program,
CFGBACK.EXE, can be found in the \Other\Misc\Cfgback directory on the
Windows 95 CD-ROM. This utility lets you create up to nine different backup
copies of the Registry, which it stores, with the extension RBK, in your
\Windows directory. If your system is set up for multiple users, CFGBACK.EXE
won't back up the USER.DAT file.
After
you have backed up your Registry, you can copy the RBK file onto a floppy disk
for safekeeping. However, to restore from a backup, the RBK file must reside in
the \Windows directory. Windows 95 stores the backups in compressed form, which
you can then restore only by using the CFGBACK.EXE utility.
In
the Windows directory there are several hidden files, four of these will be SYSTEM.DAT
& USER.DAT, your current registry, and SYSTEM.DA0 & USER.DA0,
a backup of your registry. Windows 9x has a nice feature in that every time it
appears to start successfully it will copy the registry over these backup
files, so just in case something goes wrong you can restore it to a known good
state. To restore the registry follow these instruction:
1.
Click the Start button, and then click Shut Down.
2.
Click Restart The Computer In MS-DOS Mode, then click Yes.
3. Change to your
Windows directory. For example, if your Windows directory is c:\windows, you
would type the following:
cd c:\windows
4. Type the following commands, pressing ENTER after each one. (Note that SYSTEM.DA0 and USER.DA0 contain the number zero.)
attrib -h -r -s system.dat
attrib -h -r -s system.da0
copy system.da0 system.dat
attrib -h -r -s user.dat
attrib -h -r -s user.da0
copy user.da0 user.dat
5. Restart your computer.
Following this
procedure will restore your registry to its state when you last successfully
started your computer.
If all else fails,
there is a file on your hard disk named SYSTEM.1ST that was created when
Windows 95 was first successfully installed. If necessary you could also change
the file attributes of this file from read-only and hidden to archive to copy
the file to C:\WINDOWS\SYSTEM.DAT.
Windows 98
Microsoft
Windows 98 automatically creates a backup copy of the registry every time
Windows starts, in addition to this you can manually create a backup using the Registry
Checker utility by running SCANREGW.EXE from Start | Run menu.
What to do if you get a
Corrupted Registry
Windows 95, 98 and NT/2000 all have a simple registry backup mechanism that is
quite reliable, although you should never simply rely on it, remember to always
make a backup first!
Windows NT/2000
On Windows NT/2000 you
can use either the "Last Known Good" option or RDISK to restore to
registry to a stable working configuration.
Here are the
instructions for restoring the Registry from a “Last Known Good” state.
NUM LOCK must be off before the arrow keys on the numeric keypad will function.
Notes
Cleaning the Registry
Although it's possible
to manually go through the Registry and delete unwanted entries, Microsoft
provides a tool to automate the process, the program is called RegClean.
RegClean analyzes Windows Registry keys stored in a common location in the
Windows Registry. It finds keys that contain erroneous values, it removes them
from the Windows Registry after having recording those entries in the Undo.Reg
file.
Registery Classes in .Net
.Net
provides two main classes for accessing and modifying registry entries. One
class is called Registry which has a few static properties that allow you to
access different registry hives, the other class is called RegistryKey – which
as the name implies is used to create and manipulate registry keys. The
RegistryKey class can do most modifications except for the security settings.
Both of these classes require the Microsoft.Win32 namespace.
The
RegistryKey class has seven properties named after the seven hives in the
registery i.e, ClassesRoot, CurrentConfig, CurrentUser, LocalMachine, Users,
DynData, and PerformanceData.
Example: The following code returns a
reference to the SQL server key.
RegistryKey
rk = Registry.LocalMashine;
RegistryKey
rkSW = rk.OpenSubKey(“Software”);
RegistryKey
rkSqlserver = rkSw.OpenSubKey(“MSSQLServer”);
The
above technique only gives you a read-only access. If you wanted to modify a
key or create subkeys inside it, then you need to open the key with another
overridden function (still called OpenSubKey) that takes two parameters. For
example the above code will change to as shown below if modifications are
intended in the MSSQLServer key.
RegistryKey
rk = Registery. LocalMashine;
RegistryKey
rkSW = rk.OpenSubKey(“Software”);
RegistryKey
rkSqlserver = rkSw.OpenSubKey(“MSSQLServer”, true);
The OpenSubKey method returns null if the key
is not present. If your intention is to create a key, then the appropriate
method to use is called CreateSubKey( ). This method allows read/write access
to the key e.g.,
RegistryKey
rk = Registery. LocalMashine;
RegistryKey
rkSW = rk.OpenSubKey(“Software”,true);
RegistryKey
rkMs = rkSw.CreateSubKey(“MySoft”);
If the MySoft key already exists, then the
CreateSubKey( ) method returns a reference to the existing key.
You will rarely write code to delete registry
keys. But if that is the intention, then there is the DeleteSubKey( ) method
that will do the job. Once again, you have to be very careful in deleting any
information in the registry.
Once you have a reference to the key that you
would like to modify, you can use the SetValue( ) method (or the GetValue( ) to
read a value stored in the key). The SetValue( ) method can decide from the
type of second parameter whether the data type stored in the registry will be
REG_SZ or REG_DWORD, or REG_BINARY e.g.,
RegistryKey
rk = Registry.LocalMashine;
RegistryKey
rkSW = rk.OpenSubKey(“Software”);
RegistryKey
rkMs = rkSw.CreateSubKey(“MySoft”);
rkMs.SetValue(“Greeting”,”Welcome
to MySoft”); // treats param as REG_SZ
rkMs.SetValue(“Version”,2); // treats 2 as REG_DWORD
When you use the GetValue( ) method to
retrieve a value from the registry key, you need to type cast it to an
appropriate value as the data is brought back as an object reference e.g.,
string
msg = (string) rkMs.GetValue(“Greeting”);
int
ver = (int)rkMs.GetValue(“version”);
After you are done reading or modifying a
key, you should close the key, e.g.,
rkMs.Close(
);
One
of the common uses of the registry is to store the position, size and edit
preferences of the user in an application. This way once you restart the
application after shutting it down, it appears the same way, the last time you
had used it. We will create a simple notepad like word processor and use the
registry to store important information such as size, position, and background
color etc.. The basic idea in this case is to use the dispose method to store
the important information in the registry and the form constructor to read from
the registry and set the values.
Example: Creating a simple NotePad like Word
Processor. Note that a word processor is simply a text box that occupies the
entire client area.
Create
a new windows project. Name the project NotePad. Put a text box in the form
with a name of txtNotePad. Set the multi-line property of this text box to true
and the scrollbars property to both. The Resize event for the form will make
the text box as large as the entire client area. Change the text property of
the form to “My NotePad”.
Add a main menu control with the following
menus. Name the menus appropriately e.g., the File menu will be named as mnuFile
while the New menu under it will be named as mnuFileNew.
File Edit Color
New Copy Back Color
Open Cut Text Color
------ Paste
Save
Save
As
------
Exit
Add the System.IO namespace to the top of the
form. You will need this for the file and stream type of classes.
Add a data member called currentFilename to
the form class as shown below.
public class
Form1 : System.Windows.Forms.Form
{
string currentFilename ;
The different event handlers for the
different menu items are shown below.
public Form1()
{
//
// Required for Windows Form Designer support
//
InitializeComponent();
currentFilename =
"";
}
private void
Form1_Resize(object sender, System.EventArgs e)
{
txtNotePad.Left
= 0;
txtNotePad.Top
= 0;
txtNotePad.Width
= ClientRectangle.Width;
txtNotePad.Height
= ClientRectangle.Height;
}
private void
Form1_Load(object sender, System.EventArgs e)
{
Form1_Resize(sender,e);
}
private void
mnuEditCopy_Click(object sender,
System.EventArgs e)
{
txtNotePad.Copy();
}
private void
mnuEditCut_Click(object sender,
System.EventArgs e)
{
txtNotePad.Cut();
}
private void
mnuEditPaste_Click(object sender,
System.EventArgs e)
{
txtNotePad.Paste();
}
private void
mnuFileOpen_Click(object sender,
System.EventArgs e)
{
txtNotePad.Text
= "";
currentFilename="";
OpenFileDialog
openfDlg = new OpenFileDialog();
openfDlg.Filter
= "Text Files | *.txt";
string filename;
if (openfDlg.ShowDialog() == DialogResult.OK)
{
filename
= openfDlg.FileName;
currentFilename
= filename;
FileInfo
fi = new FileInfo(filename);
StreamReader
rstr = fi.OpenText();
string []sline = new string[65535];
// max lines a text box can hold
int count = 0;
if (rstr != null)
{
count
= 0;
sline[count++]
= rstr.ReadLine();
while (sline[count-1] != null)
{
sline[count++]
= rstr.ReadLine();
if (count >= 65536) break;
}
rstr.Close();
string []finalSize = new
String[count];
// find exact size of line array otherwise blank
// blank lines will show up in editor
for (int i = 0; i
< count; i++)
finalSize[i]=sline[i];
txtNotePad.Lines
= finalSize;
}
}
}
private void
mnuFileSaveAs_Click(object sender,
System.EventArgs e)
{
string
filename="";
SaveFileDialog
savefDlg = new SaveFileDialog();
if (savefDlg.ShowDialog() == DialogResult.OK)
{
filename
= savefDlg.FileName;
SaveData(filename);
}
}
private void
mnuFileSave_Click(object sender, System.EventArgs
e)
{
SaveData(currentFilename);
}
private void
SaveData(string filename)
{
StreamWriter
wstr = new StreamWriter(
filename,false,System.Text.Encoding.Unicode);
foreach(string sline in txtNotePad.Lines)
wstr.WriteLine(sline);
wstr.Close();
txtNotePad.SelectionLength=0;
}
private void
mnuFileNew_Click(object sender,
System.EventArgs e)
{
txtNotePad.Text
= "";
currentFilename="";
}
private void
mnuFileExit_Click(object sender,
System.EventArgs e)
{
Application.Exit();
}
private void
Form1_Closing(object sender,
System.ComponentModel.CancelEventArgs e)
{
mnuFileExit_Click(sender,e);
}
private void
mnuColorBack_Click(object sender,
System.EventArgs e)
{
ColorDialog
cd = new ColorDialog();
if (cd.ShowDialog() == DialogResult.OK)
txtNotePad.BackColor
= cd.Color;
}
private void
mnuColorText_Click(object sender,
System.EventArgs e)
{
ColorDialog
cd = new ColorDialog();
if (cd.ShowDialog() == DialogResult.OK)
txtNotePad.ForeColor
= cd.Color;
}
Exercise:
Build
and test the NotePad editor. You will notice some problems such as if you run
the application and click on File->Save menu, a run time error is generated.
Similarly if you type something and then terminate the application, it does not
prompt you to save the data. Try to discover other problems and fix them.
Solution:
The solution to first problem is to disable
the Save menu if a file has not been opened yet or to invoke the FileSaveAs
menu whenever some clicks on the File->Save and the name of the file is
empty.
The solution to the problem of quitting
before the user has a chance to save the data can be solved by adding a bool
type variable called isDirty in the form as a data member. The constructor of
the form will initialize it to false. Then you will write a TextChanged event
handler for the txtNotePad which will look as:
private
void txtNotePad_TextChanged(object sender, System.EventArgs e)
{
isDirty = true;
}
You can add another function to the form code
which will prompt the user to save the data or not. The code for this function
is shown below.
private void
PromptSave()
{
string question;
if (currentFilename == "")
question
= "Save Changes to a File?";
else
question
= "Save Changes Made in "
+
currentFilename;
if (MessageBox.Show(question,"Save File?",
MessageBoxButtons.YesNo)
== DialogResult.Yes)
{
if (currentFilename == "")
mnuFileSaveAs_Click(null,null);
else
mnuFileSave_Click(null,null);
}
}
private void
mnuFileExit_Click(object sender,
System.EventArgs e)
{
if (isDirty)
PromptSave();
Application.Exit();
}
You will need to add the Form Closing event handler.
private void
Form1_Closing(object sender, System.ComponentModel.CancelEventArgs
e)
{
mnuFileExit_Click(sender,e);
}
Add the following lines shown in bold to the beginning of the mnuFileOpen handler.
private void
mnuFileOpen_Click(object sender,
System.EventArgs e)
{
if (isDirty)
PromptSave();
txtNotePad.Text = "";
Add the following lines shown in bold to the
beginning of the mnuFileNew handler.
private
void mnuFileNew_Click(object
sender, System.EventArgs e)
{
if
(isDirty)
PromptSave();
txtNotePad.Text =
"";
currentFilename="";
}
Program Modification so that
NotePad position, size and back color can be stored and retrieved from Registry
Add the following two methods to the form code.
void
SaveSetting() //
saves info in registry
{
RegistryKey
rk = Registry.LocalMachine;
RegistryKey
rkSw = rk.OpenSubKey("Software",true);
RegistryKey
rkAm = rkSw.CreateSubKey("AusifM Software");
RegistryKey
rkFr = rkAm.CreateSubKey("NotePadFrame");
rkFr.SetValue("BackColor",(object)this.txtNotePad.BackColor.ToKnownColor());
rkFr.SetValue("Red",(object)(int)this.txtNotePad.BackColor.R);
rkFr.SetValue("Green",(object)(int)this.txtNotePad.BackColor.G);
rkFr.SetValue("Blue",(object)(int)this.txtNotePad.BackColor.B);
rkFr.SetValue("Width",(object)this.Width);
rkFr.SetValue("Height",(object)this.Height);
rkFr.SetValue("X",(object)this.DesktopLocation.X);
rkFr.SetValue("Y",(object)this.DesktopLocation.Y);
rkFr.SetValue("WindowState",(object)this.WindowState.ToString());
rkFr.Close();
}
bool GetSetting()
// Retrieves info in registry
{
RegistryKey
rk = Registry.LocalMachine;
RegistryKey
rkSw = rk.OpenSubKey("Software");
RegistryKey
rkAm = rkSw.OpenSubKey("AusifM Software");
if (rkAm == null)
return false;
RegistryKey
rkFr = rkAm.OpenSubKey("NotePadFrame");
if (rkFr == null)
return false;
int red = (int)rkFr.GetValue("Red");
int green = (int)rkFr.GetValue("Green");
int blue = (int)rkFr.GetValue("Blue");
this.txtNotePad.BackColor = Color.FromArgb(red,green,blue);
int x = (int)rkFr.GetValue("X");
int y = (int)rkFr.GetValue("Y");
this.DesktopLocation = new
Point(x,y);
this.Width = (int)rkFr.GetValue("Width");
this.Height = (int)rkFr.GetValue("Height");
string wndState = (string)rkFr.GetValue("WindowState");
this.WindowState = (FormWindowState)
FormWindowState.Parse(WindowState.GetType(),wndState);
rkFr.Close();
return true;
}
Add the Microsoft.Win32
namespace in the beginning of the form code.
using Microsoft.Win32; // for registery classes
Modify the constructor and
the dispose method to look as:
public Form1()
{
InitializeComponent();
currentFilename
= "";
isDirty
= false;
if
(GetSetting() == false)
MessageBox.Show("No
info in Registery");
else
this.StartPosition
= FormStartPosition.Manual;
}
protected override void Dispose( bool
disposing )
{
if( disposing )
{
if (components != null)
{
components.Dispose();
}
}
SaveSetting();
base.Dispose( disposing );
}
Build and test the application. Examine the registry entries to see how the entries for your NotePad look like.