Skip to content

Instantly share code, notes, and snippets.

@paucoma
Last active March 9, 2024 14:06
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save paucoma/ef91a9f3d1e7e311779f9c8d9e9c51b8 to your computer and use it in GitHub Desktop.
Save paucoma/ef91a9f3d1e7e311779f9c8d9e9c51b8 to your computer and use it in GitHub Desktop.
Windows Extension Specific Context Menu Modification

Windows context Menu Handlers.

-----Considerations -----

In general, HKEY_CLASSES_ROOT is intended to be read from but not written to, although one can write to it.

The HKEY_CLASSES_ROOT subtree is a view formed by merging
  • HKEY_CURRENT_USER\Software\Classes
    • file type registration visible to the current user only
  • HKEY_LOCAL_MACHINE\Software\Classes
    • globally register a file type on a particular computer

-------Default Program additional Menu Items or System File Association -------

There are two main approaches:
  • One id to extend the context menu defined by the selected default program (ProgID)
  • The Other is to extend the context menu based on System file Extension Association *"ClassesKey"* :code:`SystemFileAssociations`

The (ProgID) defined verbs have priority over the same ones defined in :code:`...SystemFileAssociations` , but are dependent on that particular Application, When that application uninstalls, it would normally delete its registry entry, along with what modifications/additions you may have done under that key. Or if the default (ProgID) is changed, your modifications will no longer be in effect.

The :code:`...SystemFileAssociations` registrations are stable even when users change/uninstall the default programs.

When and where to activate

run-> regedit

  • Navigate to one of the flowwing Classes Key (Folders)
    • HKEY_CLASSES_ROOT
    • HKEY_CURRENT_USERSoftwareClasses
    • HKEY_LOCAL_MACHINESoftwareClasses

(ProgID) Method: - Find the Extension specific Handler Class, e.g. .xls

\Computer\HKEY_CLASSES_ROOT\.xls\

[String Value] Name:"(Default)" Data:"ExcelViewer.Sheet.8"

  • Find the Handler Class (ProgID) context Menu Definition

\Computer\HKEY_CLASSES_ROOT\ExcelViewer.Sheet.8\shell\

  • Navigate to the :code:`shell` subkey

\Computer\HKEY_CLASSES_ROOT\ExcelViewer.Sheet.8\shell\


:code:`...SystemFileAssociations` Method

  • Navigate to :code:`HKEY_CURRENT_USERSoftwareClassesSystemFileAssociations`
  • locate :code:`.oxps` key , if it doesnt exist, create it (right click --> New --> Key)
  • locate :code:`shell` subkey, if it doesn't exist, create it

  • Within the \shell\` key there will be a [String Value] Name:":code:(Default)" Data:":code:`View"
    • This is the Key Name which is used by default. There will be a subkey with this very name (View in this case)
    • Used when you double click shown as the bold option in the context menu.
  • Define the context Menu, additional keys
Within the shell folder there are other folders named keys.
  • Each has a String Value Named :"(Default)" with the Value of the text that should appear in the context menu. e.g. Data:"&View"
    • The Ampersand & is to provide a shortcut letter to this menu item amoung the other one that may be on the list. The ampersand can be placed anywhere in the text and the letter the Ampersand is infront of will define that shortcut letter.
      • When you press that letter with the context menu open it will execute that command unless there are more than one menu item with the same assigned letter.
        • In this case the selected item will cycle between the different menu items that have that same shortcut key. You can then execute the command by pressing spacebar or enter.

Within each unique shell folder named key there will be a subkey (folder) named "command" which will contain a String Value Named: "(Default)" with the value of the command to execute when this menu item is selected and executed. e.g. C:\Prog...\...\...\xlview.exe "%1" - The Percentage is passing the first argument to the program in this case the selected file name.

Command interpreted Arguments

The command which can be run accepts several percent Arguments.

Parameter example description
%0 C:\tmp\fn.ext Long File Path
%1 C:\tmp\fn.ext Long File Path
%D C:\tmp\fn.ext Long File Path
%H 0

?

%I :2113706496:3816

?

%L C:\tmp\fn.ext Long File Path
%S 1

?

%U

blank

%V C:\tmp\fn.ext Long File Path
%W C:\tmp Long Parent Folder Path
  • Any %~f1 style modifiers are not interpreted!
  • Observed in existing command strings %1 and %L are mostly used.
  • %2 or %* are blank, even if multiple files are selected.
  • When multiple files are selected and the command is executed, multiple instances of the command are executed.

Of interest I would consider %1,%L,%W , but there is not much you can program into your command line with these arguments.

Extending Command interpreted Arguments

To take advantage of %~f1 style modifiers, a work around is to create a *BATCH* file.

  • The context menu item will call the batch parameter passing it %1 or %L which contains all the info you can get anyhow.
  • The Batch file will call the command of interest.

In the command subfolder of the context menu item:

  • set the (Default) String value to "C:\opt\bin\mybatfile.bat" "%1"
  • call the command of interest from within the batch file:
    • "C:\opt\ImageMagick\convert.exe" "%1" -normalize %~dpn1_n%~x1

Here is a list of %~ style modifiers

Expression Result
:code:%~1 Removes surrounding quotes (").
%~f1 Fully qualified pathname.
%~d1 Drive letter only.
%~p1 Path only.
%~n1 Filename only.
%~x1 File extension only.
%~s1 Short DOS 8.3 file and path.
%~a1 File attributes.
%~t1 Modification date/time of file.
%~z1 Length of file in bytes.
%~$PATH:1 Long Path of First filename with extension match in Path.
  • When an absolute reference e.g. c:\tmp\a.txt is provided as argument then the parent directories and drive letters are extracted from this path.
  • When a relative reference e.g. a.txt is provided then the current working directory and drive are used.
  • these can be combined e.g. %~dpn1_n%~x1 appends _n to the filename conserving the original filename and extension.

Disabling a key

You can disable a key by

  • Deleting the key and the associated subkey
  • Inserting a String Value with the Name:"LegacyDisable"
    • LegacyDisable REG_SZ ""
  • Inserting a String Value with the Name:"Extended"
    • Extended REG_SZ ""
    • In this case you are not actually disabling the command but rather placing it in the extended Context Menu list which is opened when *holding down the shift key* while opening the context menu.

Context Menu SubMenus

Single Item:

Shell
  (Default)  REG_SZ  (value not set)
  cmd1
    (Default)  REG_SZ  <Display String>
    command
      (Default)  REG_SZ <command string>

Sub Menu Items:

Shell
  (Default)  REG_SZ  (value not set)
  SubMenuGroup
    (Default)   REG_SZ  (value not set)
    MUIVerb     REG_SZ  <SubMenu Display String>
    SubCommands REG_SZ  ""
    Shell
      (Default)  REG_SZ  (value not set)
      cmd1
        (Default)  REG_SZ  <Display String>
        command
          (Default)  REG_SZ <command string>
      cmd2
        (Default)    REG_SZ  <Display String>
        CommandFlags REG_DWORD  <display flags> 
        command
          (Default)  REG_SZ <command string>

Command Flags

The command flags are optional and some interesting ones could be:

Flag Value Description
ECF_DEFAULT 0x00 No Flags Set
ECF_HASLUASHIELD 0x10 Display UAC Icon
ECF_SEPARATORBEFORE 0x20 Separator before Item
ECF_SEPARATORAFTER 0x40 Seperator after Item

If you want more than one flag, it is just the sum of the flags to apply.

CommandFlags REG_DWORD 0x60 would be a seperator before and after the item.

Handling multiple files at once

The context Menu Handlers open a seperate instance of the defined command for all selected files when the command is selected.

To pass all selected files to a single command there are basically two options:

  • Handle active instances of the command with IPC (inter process communication) and collect the multiple files passed onto a single command with some sort of timeout.
  • Use the SendTo context menu section, which passes all selected files as arguments to the single command.

SendTo

To access the SendTo section in an explorer type shell:sendto and the Folder containing the sendto commands will open.

Within there one could creat a BAT ch file for handling the multiple arguments just as previously described.

  • To handle more than 9 files use the %* operator
    • Note that this operator is not compatible with the %~ style modifiers
    • It will list all arguments as absolute paths to the selected files.

example:

convert  %* -normalize -quality 36 -background white -page a4 %~n1.pdf

Debugging

While debugging I have found very helpful to use

cmd.exe /k echo <command of context menu item>

This opens a command window and keeps it open so that you can see what is being actually passed to the command line.

"C:\opt\bin\imgmgkcnv.bat" "%1" _p25 "-resize 25%% "

"C:\opt\ImageMagick\convert.exe" %1 %~3 %~dpn1%2%~x1

Resources

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment