3 May 2014

Creating Cascading Menu Items in Windows Explorer 7, 8 and 8.1

After creating a rather useful command-line application the other day I wanted to expose it in a user friendly way through Windows Explorer. I remembered that this could be done quite easily through the Windows Registry but most of the documentation I found on the internet was quite confusing and most only gave me a piece of the puzzle. So after a lot of trial and error I finally managed to create what I wanted to see:


My criteria

  1. Cascading menu with sub items and keyboard shortcuts
  2. Consistent ordering of menu items
  3. Separator to divide the main action from the two sub actions
  4. Menu only visible for certain types of files (in this case *.ini files)
  5. Menu items execute my program via the shell command line

But first, the complete registry code

[HKEY_CLASSES_ROOT\SystemFileAssociations\.ini]

[HKEY_CLASSES_ROOT\SystemFileAssociations\.ini\shell]

[HKEY_CLASSES_ROOT\SystemFileAssociations\.ini\shell\myactiontoplevel]
"MUIVerb"="My &Tool"
"subcommands"=""

[HKEY_CLASSES_ROOT\SystemFileAssociations\.ini\shell\myactiontoplevel\shell]

[HKEY_CLASSES_ROOT\SystemFileAssociations\.ini\shell\myactiontoplevel\shell\a_myactionmain]
@="My Main &Action"
"CommandFlags"=dword:00000040

[HKEY_CLASSES_ROOT\SystemFileAssociations\.ini\shell\myactiontoplevel\shell\a_myactionmain\command]
@="C:\\tool\\mine.exe -i \"%1\""

[HKEY_CLASSES_ROOT\SystemFileAssociations\.ini\shell\myactiontoplevel\shell\b_myactionfirst]
@="My Action &One"

[HKEY_CLASSES_ROOT\SystemFileAssociations\.ini\shell\myactiontoplevel\shell\b_myactionfirst\command]
@="C:\\tool\\mine.exe -i \"%1\" -first"

[HKEY_CLASSES_ROOT\SystemFileAssociations\.ini\shell\myactiontoplevel\shell\c_myactionsecond]
@="My Action &Two"

[HKEY_CLASSES_ROOT\SystemFileAssociations\.ini\shell\myactiontoplevel\shell\c_myactionsecond\command]
@="C:\\tool\\mine.exe -i \"%1\" -second -debug"

1) The Cascading menu

The name of the key (myactiontoplevel) must be unique and ideally not conflict with other values.

The top level menu must have the string entry "subcommands" with no text in it. Otherwise none of the child menus will show in Explorer as nested.

The "MUIVerb" value controls the text displayed for the menu item (it is also possible to skip this and just use the "default" entry for the registry key. The ampersand (&) defines the shortcut key character (will be underlined when applicable).

All nested commands sit under the \shell\ sub-key defined for the top level menu entry.

2) Consistent ordering

Windows sorts the sub menu items according to their key name (e.g. myactionfirst, myactionsecond). Therefore to ensure the correct ordering of the sub items I prefix them with a sorting character to ensure consistent sorting. The image below shows an example of what happens to the menu items if the sorting prefix is skipped in the code above.

3) Separator

The CommandFlags <dword> entry can be added to instruct Windows to add a separator menu entry. The value is of type EXPCMDFLAGS. To control the placement of the separator use either 0x40 (separator below) or 0x20 (separator above).

Following values are supported, sum to combine features
ValueDescription
0x08Entry is a separator. Consecutive separators are collapsed into a single separator
0x10Shows a UAC shield next to the menu item.
0x20Show a separator above this item
0x40Show a separator below this item

4) Showing menu item only for *.ini files

To enable the menu item only for ini files.,the root \shell\ entry can be placed either under HKEY_CLASSES_ROOT\SystemFileAssociations\.ini (as shown above) or under HKEY_CLASSES_ROOT\inifile\. There is not a clear distinction between which of these keys is better placement for your custom entry. The \inifile\ entry should already have some shell keys defined by default and these commands seem to be placed before the \SystemFileAssociations\.ini entries in the menu. Otherwise I have not noticed any other difference than that.

Do not place the registry entries under HKEY_CLASSES_ROOT\.ini as this location is only used to map to HKEY_CLASSES_ROOT\inifile (as evident by the default value). If you place any \shell\ entries under HKEY_CLASSES_ROOT\.ini they will not show up.

5) Executing a custom application

This one is relatively easy to do as you only need to point the \command\ key to the location of your executable and then place any parameters you want in the command line. By default the %1 or %0 contain the selected file path (make sure you place all %1 type of variables in quotes).

Other % macros are:
MacroDescription
%0 or %1the first file parameter. For example “C:\docs\supersecret\world.txt”. Generally this should be in quotes and the applications command line parsing should accept quotes to disambiguate files with spaces in the name and different command line parameters. Just note that if the path is not a file but a directory path then the trailing backslash will not be included, e.g. C:\docs\ will be C:\docs
%<N>(where N is 2 - 9), replace with the nth parameter
%sshow command
%hhotkey value (number, 0 if not set)
%iIDList stored in a shared memory handle is passed here. Example ":1084009376:4272"
%llong file name form of the first parameter. Note win32 applications will be passed the long file name, win16 applications get the short file name. Specifying %L is preferred as it avoids the need to probe for the application type.
%d desktop absolute parsing name of the first parameter (for items that don’t have file system paths)
%vfor verbs that are none implies all, if there is no parameter passed this is the working directory or the file path.
%wthe working directory
%uunknown
%*not supported
%~not supported

Other resources

Explicitly about creating entries in right-click menus on the Desktop and the My Computer Icon.
http://www.askvg.com/add-cascading-menus-for-your-favorite-programs-in-windows-7-desktop-context-menu/

Links to various other types of menus that can be customized
http://www.askvg.com/ultimate-tutorial-to-customize-desktop-context-menu-in-windows-vista-server-2008-and-windows-7/