
Associating Your Program with Every File: ShellExtension
Originally published on my old blog at cumps.be on February 27, 2004.
In my last article (C# Script) I spoke about adding it to the shell right-click menu. Now it’s time to implement that.
We’ll create a class (ShellExtension) that allows us to associate our program with all files. So, we’ll have one public method for that, which I’ll call AssociateProgram.
But first, some info about this.
Where are those entries stored? They all reside in the Registry, global ones live in HKEY_LOCAL_MACHINE and per-user ones in HKEY_CURRENT_USER. Our class will only use it per user, as we don’t want to spam the system.
Here is a sample registry file that will add a “test” entry which will simply open notepad:
Windows Registry Editor Version 5.00
[HKEY_CURRENT_USER\Software\Classes\*\shell\test\command]
@="notepad.exe"
Run it, and check it out. Not that useful, but it shows you the inner workings.
Let’s get started. We need Microsoft.Win32 to access the Registry.
using System;
using Microsoft.Win32;
namespace ShellExtension {
public class ShellExtension {
public ShellExtension() { }
public bool AssociateProgram(string extensionName, string filePath) {
} /* AssociateProgram */
} /* ShellExtension */
} /* ShellExtension */
We’ll add two helper methods to read and create RegistryKeys. Someday we could do something when creating a key, like log it somewhere.
The true opens the key for writing. Otherwise you’d get an UnauthorizedAccessException when creating our shell extension.
private RegistryKey GetKey(RegistryKey rootKey, string keyName) {
return rootKey.OpenSubKey(keyName, true);
} /* GetKey */
private bool CreateKey(RegistryKey rootKey, string keyName) {
return (!(rootKey.CreateSubKey(keyName) == null));
} /* CreateKey */
Now, we have to create that key. Because almost nobody has * under HKEY_CURRENT_USER.
This is the ‘biggest’ method, after we’ve made sure our key is there we only have to put our shell extension in there.
private RegistryKey SetupKeys() {
RegistryKey returnKey = null;
RegistryKey currentUser = Registry.CurrentUser;
RegistryKey softwareKey = this.GetKey(currentUser, "Software");
if (softwareKey != null) {
RegistryKey softwareClasses = this.GetKey(softwareKey, "Classes");
if (softwareClasses != null) {
RegistryKey allFiles = this.GetKey(softwareClasses, "*");
if (allFiles != null) {
RegistryKey shellExtension = this.GetKey(allFiles, "shell");
if (shellExtension != null) {
returnKey = shellExtension;
} else {
if (this.CreateKey(allFiles, "shell")) { returnKey = this.GetKey(allFiles, "shell"); }
}
} else {
if (this.CreateKey(softwareClasses, "*")) {
allFiles = this.GetKey(softwareClasses, "*");
RegistryKey shellExtension = this.GetKey(allFiles, "shell");
if (shellExtension != null) {
returnKey = shellExtension;
} else {
if (this.CreateKey(allFiles, "shell")) { returnKey = this.GetKey(allFiles, "shell"); }
}
}
} // HKEY_CURRENT_USER\Software\Classes\*
} // HKEY_CURRENT_USER\Software\Classes
} // HKEY_CURRENT_USER\Software
return returnKey;
} /* SetupKeys */
The only thing left now is to add our extension caption along with the ‘command’ key and the file path.
We use "filepath" %1 to pass the filename along.
RegistryKey shellKey = this.SetupKeys();
if (shellKey != null) {
if (this.CreateKey(shellKey, extensionName + @"\command")) {
RegistryKey extPath = this.GetKey(shellKey, extensionName + @"\command");
extPath.SetValue("", "\"" + filePath + "\" %1");
}
}
That’s it. Compile your class, reference the .dll and call it like this:
ShellExtension.ShellExtension shellAdd = new ShellExtension.ShellExtension();
shellAdd.AssociateProgram("Notepad", "notepad.exe");
I’ve uploaded the project again, the ShellExtensionDriver shows you how to associate Notepad with every file (which is very useful!).
You May Also Like

C# Script
CS-Script: a small tool that compiles and runs a single .cs file in memory, like a batch script for C#.

Including Resources in .exe
Embedding the Non-Rectangular Form's bitmap in the .exe as a resource, and loading it with one line of C#.

Non-Rectangular Form
Turning any bitmap into a non-rectangular Windows Form in C#: build a Region from every non-transparent pixel.



