BlackWasp
Windows Forms Programming
.NET 1.1

Programmatically Checking and Setting File Types

When developing a Windows Forms application that loads documents, setting custom file types adds greatly to the professional feel of the software. This article explains how to programmatically check your file type is registered and register it if not.

Why Not Register during Set-Up?

Generally the installation package for an application will modify the registry of the end user's Windows installation and set up all of the file types that are required. This is an ideal place in which to perform this action. However, it can be problematic should the user accidentally remove or reconfigure the file type. Also, with Xcopy deployment of software now a viable solution, it is possible that the installation package will never be executed. In these cases, another solution is required.

How are File Types Registered?

When a new file type is registered, several new items are inserted into the Windows registry. These items control how files of the new type will appear in Windows Explorer and how they will react to user input.

The key information that is required to be registered is as follows:

  • The file extension for the file type.
  • A unique name for the file type.
  • A descriptive, user-readable name for the file type.
  • An icon to display in Windows Explorer alongside files of the new file type.

Once a file type has been created, verbs can be added to determine how the file type reacts to user input. Each verb appears on the pop-up menu that you see when you right-click a file in Windows Explorer. eg. Run, Open, etc.

The key information required for each verb is as follows:

  • A name for the verb.
  • A display name for the verb in menus, possibly including a short-cut key.
  • The command to execute when the verb is clicked.

All of this information can be checked and registered programmatically using the .NET Framework. The remainder of this article describes the creation of the C# code required to achieve this.

WARNING: This article deals with the registry, which is responsible for the configuration of your Windows system. Errors in the registry can leave your system inoperable. No responsibility for system damage can be accepted by BlackWasp should the methods describe cause issues. If you do not accept responsibility for using the methods described here, you must not use them. It is advisable to ensure that you have a recoverable backup of your system before making registry modifications.

Microsoft.Win32 Namespace

The Microsoft.Win32 namespace contains classes for responding to system events and for manipulating the operating system configuration. We will use this class to modify the registry to add our file type and to check the registry to see if our file type exists. To make the sample code clearer, I will assume that the appropriate using statement exists in the code.

using Microsoft.Win32;

Reading from the Registry

File types are listed in the registry within the HKEY_CLASSES_ROOT section. You can see this by running the registry editor program. To run the registry editor, click Start then Run and run the program "regedt32.exe".

Each file type is held as a registry key with a name that starts with a full stop (period). In this example, we will be testing for the existence of the file type ".blackwasp", which should not exist in your registry at this time!

To read from the registry, the Registry and RegistryKey classes are used. As the registry is organised in a large hierarchical tree structure, it can be useful to create a reference to the major section and then attempt to open the keys within the section. The following code achieves this:

// Create a registry key object to represent the HKEY_CLASSES_ROOT registry section
RegistryKey rkRoot = Registry.ClassesRoot;

// Attempt to retrieve the registry key for the .blackwasp file type
RegistryKey rkFileType = rkRoot.OpenSubKey(".blackwasp");

Following execution of this code, rkFileType will contain one of two things. If the file type is currently registered, the registry key information will have been retrieved. If the file type does not yet exist, the rkFileType variable will be null. A quick check for null will deal with this in our sample.

// Was the file type found?
if (rkFileType == null)
{
    // No, so register it
}

The above code performs the simplest of checks. If the registry key of .blackwasp does not exist in the HKEY_CLASSES_ROOT section then the file type is not registered. In reality, we should check that every piece of information that we require is correctly registered using the RegistryKey.GetValue method and rectify every item where incorrect. We should also ask the user if they want our program to make those changes before going ahead; they may have unregistered our file type for a reason! I will leave you to add these checks to keep the article as short as possible.

Writing to the Registry

So far we have read the file type key from the registry and checked if the file type is registered. We will now consider modifying the registry to add our file type and all of the information surrounding it. It is important to note that our end user may be restricted by a security policy from making the modifications. In production code it would be necessary to add error trapping and recover gracefully where this restriction occurs.

Assuming that we now know that our file type needs to be registered, we can use the same Registry and RegistryKey classes to create our file type entry. This entry includes a unique name to use for our file type, we will use the name, "blackwasp.test".

// No, so register it
RegistryKey rkNew;

// Create the registry key
rkNew = rkRoot.CreateSubKey(".blackwasp");

// Set the unique file type name
rkNew.SetValue("", "blackwasp.test");

When setting the value for the registry key, two strings are passed. The first is the value name and the second is the actual value. In this case, the first string is empty to indicate that the default value for the key is to be set.

Once the file type extension has been registered, a new registry key must be created beneath HKEY_CLASSES_ROOT. This is the key that actually holds the information relating to the new file type. It is named with the unique file type that has already been associated with the file type extension. The default value for this key holds a user-readable description for the file type that will be displayed in Windows Explorer.

// Create the file type information key
RegistryKey rkInfo = rkRoot.CreateSubKey("blackwasp.test");

// Set the default value to the file type description
rkInfo.SetValue("", "BlackWasp Test File");

If you execute the code developed so far, you will be able to see the two new keys added to the registry using the registry editor. You may need to refresh the keys first. After execution, viewing a test file with the .blackwasp extension in Windows Explorer will allow you to see the file description in action. However, we have added no verbs as yet so nothing new will appear if you right-click the file.

To add a verb to the file type, we need to add two new keys. The first is named "shell" and is a sub-key of the file type information key. This means it is one lower in the hierarchy than the keys we have added so far. Within the shell key we then add one new key for each verb that we want to add to our file type.

// Create the shell key to contain all verbs
RegistryKey rkShell = rkInfo.CreateSubKey("shell");

// Create a subkey for the "Open" verb
RegistryKey rkOpen = rkShell.CreateSubKey("Open");

The default value for the new verb determines the display name for use in the shortcut menus. If not specified, the menu description will match that of the verb name. The next line of code adds this display name to enable the action in the menus and includes an ampersand to indicate that the next character is a shortcut key for the menu option. Note that the underscore indicating the shortcut key is only visible if the user has enabled underscores in their display settings.

// Set the menu name against the key
rkOpen.SetValue("", "&Open Document");

If you execute the code as it now stands, you will find that the shortcut menu displayed when right-clicking your test file now contains a new menu item. (If you have already run the program you will need to delete the .blackwasp registry key or the condition that checks for its existence to update the file type registration.) However, selecting the new menu option simply raises an error.

We now need to add an action to the verb so that Windows knows what program to run when the option is selected. This is achieved by adding a "command" subkey beneath our verb registry key.

The command must be structured correctly. Firstly it needs to include the name of the application, including the full path to the executable. To add the filename of the selected file as a parameter we use the code "%1".

Assuming that our application lives in the root of the C: drive and is named "FileTypeSetter.exe", our command will be:

c:\FileTypeSetter.exe %1

Add the following code but substitute the correct file name and path according to the name and location of the program you have created so far.

// Create and set the command string
rkNew = rkOpen.CreateSubKey("command");
rkNew.SetValue("", @"c:\FileTypeSetter.exe %1");

We are now nearly finished! If you execute the code, again bypassing the conditional statement, you will find that the test file can be double-clicked to open our application. We can also use our new menu option to open the application.

We now need to modify the Main method of our application to include checking for the name of the document to load from its first start-up parameter. I explained how to do this in the tip, Windows Forms Application Start-Up Parameters, so I will not repeat this in this article.

Finally, we can add an icon to the file type to give it a professional look. Icons are referenced by the name of the file that they exist within. If this is a true icon (.ico) file then the name itself will suffice. Where an executable or DLL contains the icon we need, the filename of the executable or DLL is required, suffixed with a comma and the icon number from the file. As you may not have an icon to hand, let's use the standard icon from Notepad. We need a new subkey of the file information key for this.

// Assign a default icon
rkNew = rkInfo.CreateSubKey("DefaultIcon");
rkNew.SetValue("", @"C:\windows\notepad.exe,0");

The program is now complete and ready for testing. Note that sometimes the default icon does not appear immediately and requires a restart of Windows Explorer to become visible. The functionality of the file type is always added immediately.

A Note for Vista Users

Vista's User Account Control (UAC) system prevents writing to the registry in this manner to normal users. To execute the sample code, the program must be compiled first. The executable file can then be right-clicked and the "Run as Administrator" option used to run the program with elevated privileges.

Link to this Page2 August 2006
RSS RSS Feed