Adding Windows context-menu actions

I ran into this problem recently: adding my own context-menu actions in Windows explorer. Whenever you right click on a file you're presented with a bevy of options—"Open," "Edit," "Edit with GIMP," etc. These actions are defined by file type in the registry. Globally, you can find the settings in HKEY_CLASSES_ROOT, and for the current user in HKEY_CURRENT_USER\Software\Classes. For the most part, you want to change the latter.

The simplest way to define a command is by defining subkeys of ".extension," "*," or "Directory." So, for example if I wanted to define an action on text files I would be working under:
or for all files:
or for all directories:
Under that key, you'll need to define the "shell" key, and under that you need to define a subkey. The name of that subkey doesn't matter, but I suppose it ought to be related. From here on I'll call it "MyAction." One value can be set, optionally, under the "MyAction" key. The default key (type REG_SZ) can be set to a string with the name that will appear in the context menu (ex. "Perform My Action"). Otherwise, the context menu will display the name of the subkey of "shell" (i.e. "MyAction"). Finally, under "MyAction," the "command" subkey must be defined, and it's default key (type REG_SZ) should contain the command string to run on the action.

Example hierarchy ("value:" prefix before a tuple of (value name, type, value)):
                value: (<default>, REG_SZ, "Open this file in Notepad")
                    value: (<default>, REG_SZ, "notepad.exe "%1"")


In Python

The following Python snippet will set it all up with it's title, handler, etc.:
#this doesn't need to be here, but you will need _winreg.
import _winreg

def define_action_on(filetype, registry_title, command, title=None):
    define_action_on(filetype, registry_title, command, title=None)
        filetype: either an extension type (ex. ".txt") or one of the special values ("*" or "Directory"). Note that "*" is files only--if you'd like everything to have your action, it must be defined under "*" and "Directory"
        registry_title: the title of the subkey, not important, but probably ought to be relevant. If title=None, this is the text that will show up in the context menu.
    #all these opens/creates might not be the most efficient way to do it, but it was the best I could do safely, without assuming any keys were defined.
    reg = _winreg.OpenKey(_winreg.HKEY_CURRENT_USER, "Software\\Classes", 0, _winreg.KEY_SET_VALUE)
    k1 = _winreg.CreateKey(reg, filetype) #handily, this won't delete a key if it's already there.
    k2 = _winreg.CreateKey(k1, "shell")
    k3 = _winreg.CreateKey(k2, registry_title)
    k4 = _winreg.CreateKey(k3, "command")
    if title != None:
        _winreg.SetValueEx(k3, None, 0, _winreg.REG_SZ, title)
    _winreg.SetValueEx(k4, None, 0, _winreg.REG_SZ, command)
To add an action:
#define an action to open notepad for any file
define_action_on("*", "OpenWithNotepad", "notepad.exe \"%1\"", title="Open with notepad!")

An Example

An example handler application:
import sys, os
print "The full path for this file is %s!" % sys.argv[1]
and to set it up:
define_action_on("*", "PrintPath", "\"C:\\Python26\\python.exe\" \"C:\\\" \"%1\"", title="Show the full path to this file")
or if you've used py2exe:
define_action_on("*", "PrintPath", "\"C:\\handler.exe\" \"%1\"", title="Show the full path to this file")
The paths may vary, of course.

Comments, Questions, Corrections?

Please, contact me.