Creating custom context menu for Windows file explorer.
Making tx, rescaling image, displaying alembic content all as fast as a right click can be.
I had always been a fan of contextual menu in interfaces. They are a very fast way to run various processes on a selected item. And at the same time you don’t have to remember which action you can run on the item, or how the action was named. You right click and everything doable is available a few pixels away from your cursor.
And I had come to the point where, while browsing my files in the file-explorer, I found that I needed to run a specific tool on a file. And then 10 min later again, and the next week again … Each time I had to open the tool (so depends how easy it is to find its executable on your system), copy the path of the file, and give it to the tool. Huh … too long I wish I could automate that.
A bit of research, and of course you can. You probably noticed that some applications you install doesn’t refrain themselves for adding actions to the context menu, so why not you ?
Why ?
You might have clicked on this article because you already knew it sounded like something you wanted to do at some point. But for the others why would you even need to add new actions to the context menu ?
To get an example that will be familiar for the 3d artists out there let’s take
the case of makeTx
. If you are using Arnold you know what I’m going to
talk about. For every texture you use in your scene, Arnold will usually
generate a version of it in its own format called tx
(nearly every
render-engine has its own). This process is
usually done automatically when you click render but there is multiple reasons
it can goes wrong, or might not just be the behavior you want. The
solution to fix it is to manually generate the tx files. To achieve that you
can use the makeTx.exe
tool that is found alongside the Arnold installation.
The particularity with that tool being that it is a Command Line Interface, which mean you dont need to go through an interface to execute actions inside.
At the end of this article, you could had something like this :
Command Line Interfaces programs
A Command Line Interface program is made to be interacted with from the command line, and not from a graphical interface like most programs. If you are not familiar with CLIs, they are going to look very unpleasant to use compared to a GUI. But their power will be found in the flexibility they offer, especially for automatizing tasks. It’s like you were ordering the program to perform an action by describing it in a sentence.
This is will be useful in our case, because this means that by passing the “right sentence” to makeTx, he could generate a tx from the file that has been selected from the right-click !
If you ever tried to double click on a .exe just to see a window open and close immediately, it’s probably because it was a CLI. By double clicking on it you executed it, it execute the task it was made for (in our case nothing because you didn’t gave it any argument), and then close once finish.
To first see what’s going on when you don’t give it arguments, let’s open the
command line. On Windows, this can be achieved using Win
+ R
then typing
cmd
and enter. You can also just search for Command Prompt
in the
Windows search bar.
Then to execute our program you need to pass the path to its executable. Easiest way is just to drag and drop the executable from the file explorer to the command prompt. You can also just copy and paste its path.
Then press enter to start executing it.
Without any argument, most CLI will just display their documentation. Which we will anyway need to open at least one time to make sure we know what arguments the tool expects.
maketx.exe
Alright, how does makeTx works ? You can see on the line Usage : maketx
[options] file...
that it expect the path of the file to be provided last,
and before some options.
The options are listed just under, and there is a lot of them. Usually options/arguments are documented but here we only have their name to guess what they are doing.
But don’t worry, no need for playing the guess game of which options does what we want. How ? Well you know Arnold already auto-convert the tx files for you, so it knows which options to use. And thankfully, the whole command used to generate the tx file is actually embedded in the tx’s metadata !
But how do I retrieve the tx’s metadata ? Well, by using an other CLI that we are going to see a bit later (oiiotool), I can retrieve it from any existing tx that have been previously generated. Here is a line stored in the metadata of a tx file :
Software: "OpenImageIO-Arnold 2.4.0dev : maketx G:/whatever/sources/FREDDY_Shoes/texturing/publish/textures-4k.v04\FREDDY_Shoes_Diffuse_Color_1001.exr --opaque-detect --constant-color-detect --monochrome-detect --fixnan box3 --oiio --attrib tiff:half 1 -v -u --unpremult --oiio --format exr"
Seems there is a lot of options used ! One important thing to keep in mind is
that those options vary depending on what kind of texture you are converting
and how the “texture node” in the source DCC is configured. The most notable
variable option being --colorconvert
(explained later), used to convert the
input file to another colorspace that might or might not be specified.
Anyway we have what we need, the whole command required to convert a file to tx. We can now have a look at how to create the context menu !
Editing the registry: Basics
Unfortunately, there is no really simple and easy way to add actions to the context menu (though there might be if you look for them on internet), at least for this article, we will have to edit the registry.
To keep it simple see the registry as a file hierarchy like we use daily, but instead of file, we are manipulating “keys” that have different values set on them. You can access keys by their path, like you would do for a file.
If you ever have to use it, you know it’s not easy to find what you are looking for. Or you are probably aware that editing the wrong stuff inside can easily break parts of your system.
To mitigate those issues we will be using .reg
files. Instead of browsing
the registry Editor we specify how we want to edit in the file. The advantages are :
- They allow for a reproducible process. That means that if your reformat your system, you don’t have to remember which registry key you created. Just execute the reg file again.
- You can easily create a copy of the initial reg file that does the inverse, meaning removing the keys instead of adding them.
Creating the .reg file
As a first step, create a blank new file like a .txt
and just replace the
extension with .reg
(you might need to display file extension in the View
menu of the file explorer if not set already).
Then right click and open the file with any text/code editor (make sure to not click on it else you will be executing it !).
Just so you get an idea of the finished product, here is an example of what we will be putting in that reg file :
Windows Registry Editor Version 5.00 [HKEY_CURRENT_USER\Software\Classes\*\shell\makeTx] "MUIVerb"="makeTx" "icon"="F:\\blog\\demo-icon.ico" "subCommands"="" [HKEY_CURRENT_USER\Software\Classes\*\shell\makeTx\shell\txconvert] "MUIVerb"="convert to .tx" [HKEY_CURRENT_USER\Software\Classes\*\shell\makeTx\shell\txconvert\command] @="cmd /k %%MAKETX%% \"%1\" --opaque-detect --constant-color-detect --monochrome-detect --fixnan box3 --oiio --attrib tiff:half 1 -v -u --unpremult --oiio --format exr"
As mentioned previously, creating keys by their path, and setting values on those keys.
On the first line, we always have to put this text :
Windows Registry Editor Version 5.00
The next important step will be to determine the root location of the key to use. This location will determine on which type of file explorer entities the action in the context menu will appear.
Here are the few options available :
All Files | HKEY_CURRENT_USER\Software\Classes\*\shell\ |
By File Extension [1] | HKEY_CURRENT_USER\Software\Classes\SystemFileAssociations\{EXTENSION}\shell |
Directories | HKEY_CURRENT_USER\Software\Classes\Directory\shell |
Directories Background | HKEY_CURRENT_USER\Software\Classes\Directory\Background\shell |
Drive | HKEY_CURRENT_USER\Software\Classes\Drive\shell |
As makeTx (and most CLI) is designed to work on files we need to choose between the 2 first keys. As a lot of image format can be converted to makeTx we are going to play the lazy card and just assume we want to this option on all file formats so we will be using the first root key.
Great, we have now the root path for each key. Now time to create the first key.
We just need a name for it (special-character-free). No need to think to hard,
we will be using just makeTx
.
Let’s put that into the reg file :
Windows Registry Editor Version 5.00 [HKEY_CURRENT_USER\Software\Classes\*\shell\makeTx]
You notice that I added a new key location shell
after our root key. It’s
needed by Windows. Now we can configure our key. We can start by configuring
which text will appear in the context-menu for this key :
Windows Registry Editor Version 5.00 [HKEY_CURRENT_USER\Software\Classes\*\shell\makeTx] "MUIVerb"="makeTx"
I could have put any sentence between the 2 double quotes, but I decided to stay simple.
Then you might want to add a icon next to your action. It can be achieved like :
Windows Registry Editor Version 5.00 [HKEY_CURRENT_USER\Software\Classes\*\shell\makeTx] "MUIVerb"="makeTx" "icon"="F:\\blog\\demo-icon.ico"
But you have to keep in mind :
- You have to put an absolute path (starting from the drive letter, not relative)
- You have to escape backward slashes like
\
->\\
- You have to use an
.ico
file. There is plenty of online converter for it. - If for whatever reason the path doesn’t exists/is not valid, you will get a default “sheet” icon.
And finally the most important option, what is executed when clicking on the action !
We have to create a new key command
and then configure it.
For the configuration we will pass a string as you would execute the program
from the command prompt.
Windows Registry Editor Version 5.00 [HKEY_CURRENT_USER\Software\Classes\*\shell\makeTx] "MUIVerb"="makeTx" "icon"="F:\\blog\\demo-icon.ico" [HKEY_CURRENT_USER\Software\Classes\*\shell\makeTx\command] @="D:\\resources\\maketx.exe"
If you remember what we tested previously, this will only display the documentation of makeTx, cause we doesn’t provide any argument. But let’s move step by step and test what we already have.
Executing the .reg file
Save your reg file from your text/code editor and double click on it. Windows will gift you 3 dialogs to accept, but that will be all you have to do.
As a safety, let’s manually check in the registry if it was registered. Open the
Registry Editor
(you can use windows search). In the window that opens,
find the “current path” field, right under the menu bar. Inside paste
the path of the key we created and press enter.
The editor should directly browse to the key.
If you would want to delete what we did, you could just delete the makeTx
key (but we will see an alternative later).
It’s a good practice that when you follow this tutorial, you casually have a look in the Registry Editor to check everything is updated as expected.
Aright in theory it should work, what about practice ? Well pick any file
in the file explorer (because remember we put it under *
which work for
all file extensions) and right click on it. You should now see the makeTx
action near the top !
Let’s test it, click on it :
Well … it just open and close. Not very useful … But this is normal, remember what I explained in the Command Line Interfaces programs, the program execute its task and then close. If we want to keep its result displayed we have to open it from the command line. And that’s a task for the next section !
Editing the registry: Advanced
The previous section allowed us to add a new simple action to the context menu, that just execute the application we gave it. But we are still missing plenty of use-cases, like how to keep the interface open in the case of a CLI, or even more importantly, how do we pass the path of the file we right-clicked on, to the command executed ?
Calling the command prompt
Let’s address the issue we stopped the previous section at. As our tool is a CLI, it close once finished. But we want to keep its result visible. Manually the solution was to execute it from an existing command prompt window. And we will do exactly the same for our context-menu action.
Get back to out .reg file and the last line where we define our command to execute.
To open the command prompt we simply need to prefix our command with
cmd /k
, so we have:
Windows Registry Editor Version 5.00 [HKEY_CURRENT_USER\Software\Classes\*\shell\makeTx] "MUIVerb"="makeTx" "icon"="F:\\blog\\demo-icon.ico" [HKEY_CURRENT_USER\Software\Classes\*\shell\makeTx\command] @="cmd /k \"D:\\resources\\maketx.exe\""
By safety we also wrapped our path between escaped double quotes, to make sure the command prompt doesn’t complain.
Save the reg file and execute it again. Find a file again, and execute the action in the context-menu as previously.
We now have a command prompt window that open and execute the maketx.exe program. But as intended, the window stays open because it was not opened by maketx but by us. Nice.
Retrieving the file selected in the command
Probably the most interesting option for our context-menu. We selected a file by right-clicking, this mean we want to execute a program on it, by passing the path of this file to the program.
For now our makeTx action only open the documentation of the program cause it doesn’t receive any argument. By passing the path of the file it should now start the conversion.
To retrieve it simple we will be using the %1
variable (it simply retrieve
the first argument passed to the command line, which is the path of the file) :
Windows Registry Editor Version 5.00 [HKEY_CURRENT_USER\Software\Classes\*\shell\makeTx] "MUIVerb"="makeTx" "icon"="F:\\blog\\demo-icon.ico" [HKEY_CURRENT_USER\Software\Classes\*\shell\makeTx\command] @="cmd /k \"\"D:\\resources\\maketx.exe\" \"%1\"\""
Again we wrap it between escaped double-quotes by safety BUT we also now double the first and last quotes, necessary when this more that one pair of quotes [4]. Else we will get a very funky behavior.
Repeat the usual steps to tests, and you should now see the file right-clicked properly converted to tx (if you selected an image format selected by maketx of course).
Passing more arguments
You remember at the beginning that I extracted the full command used by maketx on an existing .tx file ? There was a lot of additional arguments used. Let’s add them. As on my side I am using maketx from the Arnold installation I will remove all the argument that maketx will already add for me anyway (explained at the beginning of the article).
Windows Registry Editor Version 5.00 [HKEY_CURRENT_USER\Software\Classes\*\shell\makeTx] "MUIVerb"="makeTx" "icon"="F:\\blog\\demo-icon.ico" [HKEY_CURRENT_USER\Software\Classes\*\shell\makeTx\command] @="cmd /k \"\"D:\\resources\\maketx.exe\" \"%1\"\" -v -u --unpremult --format exr"
No need to escape the argument this time.
Test again, you should mainly see much more info being displayed as we used the
-v
option which means “verbose”.
And at that state we have a totally working command 🥳, but don’t leave yet, we still have a few improvements to make !
Creating a “uninstall” reg file
For now we have a single file that allow us to create the keys in the registry. But what if we want the inverse, meaning removing them ? All program can be installed and uninstalled, so it should be the same for our context-menu action.
As mentioned before you could manually dig into the registry to delete the key, but if we took the time to create a reg file, it’s not to end up browsing the registry manually to revert it.
The solution is to create a new reg file that delete the keys instead of adding them. To start just copy/paste the existing reg file we have been creating. Also open it in your text/code editor. And now very simple edit, in front of each key path, after the first bracket, add a minus character :
Windows Registry Editor Version 5.00 [-HKEY_CURRENT_USER\Software\Classes\*\shell\makeTx] "MUIVerb"="makeTx" "icon"="F:\\blog\\demo-icon.ico" [-HKEY_CURRENT_USER\Software\Classes\*\shell\makeTx\command] @="cmd /k \"\"D:\\resources\\maketx.exe\" \"%1\" -v -u --unpremult --format exr\""
That’s about it. It’s enough to tell Windows to remove the keys instead of creating them. You could simplify the file by removing the line setting values but I will leave them so I can remember exactly what I’m removing.
Now that you have 2 files (good idea to keep them side by side), you will need to remember that if you add a new key / edit an existing one in the “create” reg file, you also need to propagate the changes in the “uninstall” reg file.
And we end up with a pretty robust workflow, “install” your custom context-menu in one double-click and “uninstall” it the same way ! Without having to remember which key you added or manually browsing the registry editor.
Using environment variables for robustness
In all the previous examples we have been using an absolute path to
maketx.exe
. Let’s imagine your directly picked the maketx located in your
Maya Arnold installation, or whatever other DCC. What happens if you uninstall
that version ? Well your command will break. You will have to edit the reg file
with the new maketx path and edit it again …
But wait ! I could just copy maketx.exe to one of my personal resources directory so I’m sure it will not be deleted when uninstalling Arnold !
And you’d be right, maketx is a standalone program that doesn’t need anything else to work so you could just copy it anywhere else. But what happens when you want to upgrade your maketx version ? Or you move it. Well you have to go find and update the reg file to execute it again. Not the most annoying task, but we can do better.
Introducing environment variables. A system wide way to set and query values. I will not make a full tutorial on them so we will skip to the essential. Feel free to browse the internet to learn more about them.
- In the Window search bar type “environment” and select “Edit Environment variable”
- Select Edit
- Create a new variable at user level
- Fill the values, we will be naming it
MAKETX
. (Do NOT wrap it in quotes like in the example picture). - “Ok” for all dialogs.
And now to get the environment variable value in our command we need to use
the batch syntax
%ENVVARNAME%
:
Windows Registry Editor Version 5.00 [HKEY_CURRENT_USER\Software\Classes\*\shell\makeTx] "MUIVerb"="makeTx" "icon"="F:\\blog\\demo-icon.ico" [HKEY_CURRENT_USER\Software\Classes\*\shell\makeTx\command] @="cmd /k \"\"%%MAKETX%%\" \"%1\"\" -v -u --unpremult --oiio --format exr"
A lot going on the “escaping” side here (it is teh biggest source of issue) :
- the
%
need to be escaped by doubling it so the variable is resolved only when cmd dialog is opened. - we again need to escape the variable MAKETX with quotes around it as it’s a path.
Like for
%1
- we need to double escape the first and last quotes in the whole command again (needed when there is more than 2 quotes in the command) [4]
Same routine, save and test. Everything should just work like before.
Hopefully you should never have to get back to your reg file to edit it now.
Auto-generating the .reg files
For the more technical person that will be reading this article. I already simplified all the steps above by creating a python CLI.
It allow to write the key structure as a json with a bunch of workflow optimizations, like relative paths, variables, … so the whole process should be much faster and much less human-error prone.
Troubleshooting
Most of the time it will be a character escaping issue.
- Making sure paths in the reg files have their backslashes escaped. Example :
C:\test\test.bat
->C:\\test\\test.bat
- Making sure paths in the reg files are wrapped between double quotes. Example :
C:\\test\\test.bat
->\"C:\\test\\test.bat\"
- When you have more than 1 pair of quote in your command line, you will need to
double escape them. Example :
@="cmd /k \"F:\\softwares\\ffmpeg.bat\" \"D:\\project\\specificvideo.mp4\""
need to be converted to
@="cmd /k \"\"F:\\softwares\\ffmpeg.bat\" \"D:\\project\\specificvideo.mp4\"\""
By doubling the first and last double-quote.
More on that here : https://ss64.com/nt/syntax-esc.html
Those rules are for the commands in the reg files. Not for batch files !
Do not hesitate to join the discord linked below and ask, if you have any more issue.
Changelog
13-07-2023
: fixed some%1
argument not wrapped in quotes. Thanks to Slava.
References
- 1.
- ^ https://stackoverflow.com/a/47745854/13806195
- 2.
- ^ https://stackoverflow.com/questions/48625223/is-there-a-maximum-right-click-context-menu-items-limit
- 3.
- ^ https://en.wikipedia.org/wiki/Batch_file
- 4.
- ^ a b https://ss64.com/nt/syntax-esc.html
- 5.
- ^ https://ss64.com/nt/for_r.html
- 6.
- ^ https://openimageio.readthedocs.io/en/latest/maketx.html#cmdoption-colorconvert
- 7.
- ^ https://openimageio.readthedocs.io/en/latest/maketx.html#cmdoption-colorconfig
- 8.
- ^ https://en.wikibooks.org/wiki/Windows_Batch_Scripting#Percent_tilde