Context Menus

22/04/2024 Brian Saladino   ID: 2502646

Context menus are the list of options displayed when right-clicking on a file or folder in Windows Explorer. A context menu holds shortcuts to essential applications that may apply to the selected file or folder. For example, if you have WinRar installed on your device, you'll see a WinRar option when you right-click on a file or folder. This acts as a shortcut to quickly use the WinRar functionality directly on a given file or folder without having to open WinRar to do so.

It's important that applications packaged with Alchemy are still able to register within context menus—regardless of the age of the application. There are four options available to achieve this:

There are four methods that can be used to register an application within a context menu:

  • Configuring the application path directly in the registry.
  • Referencing a COM GUID which points to a DLL that implements the older IContextMenu COM object.
  • Referencing a COM GUID which points to a DLL that implements the newer IExplorerCommand COM object.

This article walks you through the various methods applications use to appear in context menus.

Delete

Note

This article does not include any information regarding the Open With menu option in the Windows Explorer context menu.

Context Menu Methods

There are four methods that can be used to register an application within a context menu:

  • Configuring the application path directly in the registry.
  • Referencing a COM GUID which points to a DLL that implements the older IContextMenu COM object.
  • Referencing a COM GUID which points to a DLL that implements the newer IExplorerCommand COM object.
  • Packaging a COM inside of a UWP application that implements an IExplorerCommand object (Windows 11 only).

The following sections outline the details of each method.

Application Path

The simplest method of surfacing an application in a context menu is to provide the path to the executable in the registry itself. Below is an example of how the application VSCode registers itself in context menus:

The Regkey path Computer\HKEY_CLASSES\*\shell\VSCode\command contains the default value "C:\Users\Username\AppData\Local\Programs\Microsoft VS Code\Code.exe" "%1".

Additionally, the Regkey path Computer\HKEY_CLASSES_ROOT\*\shell\VSCode\ contains the default value Open with Code.

By including this in the registry, the option to Open with Code is displayed whenever you right-click on a file in Windows Explorer. And when you click this option, the designated file path is executed, with Windows Explorer automatically replacing the %1 included in the registry with the file that's been right-clicked.

If this application were packaged with Alchemy, the packager tool automatically updates the registry to look something like this:

"C:\PathToPackage\Cloudhouse.Container.Run.exe" /RunConditions FileArgs /fileargs /f "C:\<Path to package>\ProgData\C\Users\Username\AppData\Local\Programs\Microsoft VS Code\Code.exe" "%1".

Here, you can see the path to Cloudhouse.Container.Run.exe is included prior to the path to the application. This ensures the application is launched via Alchemy.

IContextMenu

Using the IContextMenu object to surface an application in context menus requires a degree of separation between the Regpath used to configure the context menu and the Regpath used to tell Windows where to find the DLL. The overall process looks like this:

  1. Register the CLSID of the IContextMenu object and tell it where to find the DLL.
  2. Register the context menu into the appropriate ShellEx registry path.

The sections below walk you through each of these steps.

Registering the CLSID

Let's say an application has the CLSID of {12341234-1234-1234-1234-123412341234}. The Regpath to register this CLSID would look like this:

HKEY_CLASSES_ROOT\CLSID\{12341234-1234-1234-1234-123412341234}\InprocServer32.

And the default value will be the path to the DLL file:

C:\pathtoapp\contextmenufile.dll.

Registering the IContextMenu

To register the IContextMenu, use the following Regpath, where AppsContextMenu is the unique name chosen by the application:

HKEY_CLASSES_ROOT\*\shellex\ContextMenuHandlers\AppsContextMenu.

This Regpath contains the following default value:

{12341234-1234-1234-1234-123412341234}.

Now, when you right-click on a file in Explorer, it will recognize that there is a CLSID that needs to be included in the context menu. Using the Regpaths above, that DLL will be found, loaded into memory, and executed so it appears in the context menu.

You could also achieve this by registering the IContextMenu to the following path:

HKEY_CLASSES_ROOT\Folder\shellex\ContextMenuHandlers\AppsContextMenu.

Virtualising the IContextMenu

In order to virtualise this context menu, we will need to pass it through our ContextMenuProxy DLL.

The process to configure and virtualise a context menu which uses an IContextMenu DLL is as follows:

  1. Register the CLSID of the IContextMenu object and tell it where to find the DLL.
  2. Register the CLSID of the Context Menu Proxy and tell it where to find the Proxy DLL.
  3. Connect the Proxy CLSID to the Context Menu CLSID.
  4. Register the Proxy Context Menu into the appropriate ShellEx registry path.

Registering the CLSID of the IContextMenu

As a simple example, let's say that an application has a Context Menu with the CLSID of {12341234-1234-1234-1234-123412341234}.

Then registering the CLSID would usually look something like this, under the following Regpath:

HKEY_CLASSES_ROOT\CLSID\{12341234-1234-1234-1234-123412341234}\InprocServer32.

The default value will be the path to the DLL file:

C:\pathtoapp\contextmenufile.dll.

Registering the CLSID of the Context Menu Proxy

The Context Menu Proxy uses hardcoded CLSID's. If no other context menus are packaged on the environment, then the first available would be {e3fadca7-01d9-4a5a-8858-da5dd2afc6f1}.

The registering the CLSID would usually look something like this, under the following Regpath:

HKEY_CLASSES_ROOT\CLSID\{e3fadca7-01d9-4a5a-8858-da5dd2afc6f1}\InprocServer32.

The default value will be the path to the DLL file:

C:\PathToPackage\ContextMenuProxy.dll.

Connecting the Proxy CLSID to the Context Menu CLSID

Now we need to configure the Cloudhouse hive to redirect our Proxy CLSID to the original Context Menu CLSID.

Under the following Regpath:

HKEY_LOCAL_MACHINE\SOFTWARE\Cloudhouse\ContextMenuProxy\{e3fadca7-01d9-4a5a-8858-da5dd2afc6f1}.

The key CLSID will have a value which contains the context menu CLSID.

{12341234-1234-1234-1234-123412341234}.

Registering the Context Menu Proxy to the Appropriate ShellEx

The following Regkey path (where AppContextMenu is the unique name chosen by the application):

HKEY_CLASSES_ROOT\*\shellex\ContextMenuHandlers\AppsContextMenu.

Contains the following default value:

{e3fadca7-01d9-4a5a-8858-da5dd2afc6f1}.

Now all interactions with the original Context Menu will happen in a virtualised process, taking advantage of all file and registry redirections and ensuring that when clicked, the application will launch fully virtualised under Alchemy.

IExplorerCommand

Context Menus which implement the IExplorerCommand object are configured very similarly to IContextMenu.

The overall process to configure a Context Menu which uses an IExplorerCommand DLL is this:

  1. Register the CLSID of the IExplorerCommand object and tell it where to find the DLL.
  2. Register the Context Menu into the appropriate ShellEx registry path.


Registering the CLSID

This is the same as registering an IContextMenu, as laid out above. As a simple example, let's say that an application has a Context Menu with the CLSID of {12341234-1234-1234-1234-123412341234}.

The, registering the CLSID would usually look something like this, under the following Regpath:

HKEY_CLASSES_ROOT\CLSID\{12341234-1234-1234-1234-123412341234}\InprocServer32.

The default value will be the path to the DLL file:

C:\pathtoapp\contextmenufile.dll.

Registering the IContextMenu

This is where the IExplorerCommand differs from the IContextMenu. We don't register the context menu under a ShellEx\ContextMenuHandlers\ Regpath. Instead, we use Shell. The following Regkey path (where AppsContextMenu is the unique name chosen by the application):

HKEY_CLASSES_ROOT\*\shell\AppsContextMenu.

Contains the following value for the string ExplorerCommandHandler:

{12341234-1234-1234-1234-123412341234}.

Now when you right-click on a file in Explorer, it will discover that there is a CLSID that it needs to instantiate for the Context Menu. It will look up the location of the DLL, load it into memory, and execute it.

We could also register it to the following path:

HKEY_CLASSES_ROOT\Folder\shell\AppsContextMenu.

And that would cause a context menu to appear when right-clicking on folders.

Virtualising the IExplorerCommand

To virtualise this context menu, we will need to pass it through our ContextMenuProxy DLL.

The overall process to configure and virtualise a Context Menu which uses an IExplorerCommand DLL is as follows:

  1. Register the CLSID of the IExplorerCommand object and tell it where to find the DLL.
  2. Register the CLSID of the Context Menu Proxy and tell it where to find the Proxy DLL.
  3. Connect the Proxy CLSID to the Context Menu CLSID in the Cloudhouse hive.
  4. Register the Proxy Context Menu into the appropriate Shell registry path.

Registering the CLSID of the IExplorerCommand

As a simple example, let's ay an application has a Context Menu with the CLSID of {12341234-1234-1234-1234-123412341234}.

Then registering the CLSID would usually look something like this, under the following Regpath:

HKEY_CLASSES_ROOT\CLSID\{12341234-1234-1234-1234-123412341234}\InprocServer32.

The default value will be the path to the DLL file:

C:\pathtoapp\contextmenufile.dll.

Registering the CLSID of the Context Menu Proxy

The Context Menu Proxy uses hardcoded CLSIDs. If no other context menus are packaged on the environment, then the first available would be {e3fadca7-01d9-4a5a-8858-da5dd2afc6f1}.

Then registering the CLSID would usually look something like this, under the following Regpath:

HKEY_CLASSES_ROOT\CLSID\{43c545bd-0ae1-4db9-8d15-090a1578ff01}\InprocServer32.

The default value will be the path to the DLL file:

C:\PathToPackage\ContextMenuProxy.dll.

Connecting the Proxy CLSID to the Context Menu CLSID

Now we need to configure the Cloudhouse hive to redirect our Proxy CLSID to the original Context Menu CLSID.

Under the following registry path:

HKEY_LOCAL_MACHINE\SOFTWARE\Cloudhouse\ContextMenuProxy\{43c545bd-0ae1-4db9-8d15-090a1578ff01}.

The key CLSID will have a value which contains the context menu CLSID:

{12341234-1234-1234-1234-123412341234}.

Registering the Context Menu Proxy to the Appropriate ShellEx

The following Regkey path (where AppsContextMenu is the unique name chosen by the application):

HKEY_CLASSES_ROOT\*\shell\AppsContextMenu.

Contains the following value for the string ExplorerCommandHandler:

{43c545bd-0ae1-4db9-8d15-090a1578ff01}.

Now all interactions with the original Context Menu will happen in a virtualised process, taking advantage of all file and registry redirections to ensure that, when clicked, the application will launch fully virtualised under Alchemy.

Windows 11 Context Menus

Currently, the Windows 11 context menus are not supported by Alchemy.

ContextMenuProxy in Action

From a high level perspective, the Context Menu Proxy works like this:

  1. User right-clicks on a file.
  2. The ContextMenuProxy DLL is initiated and that connects to ContextMenuLauncher (or its 32bit version) via COM (if ContextMenuLauncher is not running it will spawn a new one).
  3. ContextMenuLauncher (which is virtualised by Alchemy) initialises the application's context menu and sends all data (menu text, icons, etc.) back to the Proxy.
  4. The ContextMenuProxy displays the menu items.
  5. The user clicks on an option.
  6. The Proxy tells ContextMenuLauncher to invoke the selected option.

Because ContextMenuLauncher is virtualised by Alchemy, when it initialises and communicates with the application's Context Menu, all interactions are virtualised.

Delete

Note

Because ContextMenuLauncher is virtualised by Alchemy, it means that there is one for each package deployed on the environment. If there are three packages with context menus, then they all will have their own copy of ContextMenuLauncher with their own redirection rules. This is regardless of how many context menus exist in a single package. If 100 context menus exist in a single package, then only one instance of ContextMenuLauncher is required.

Troubleshooting the ContextMenuProxy

Troubleshooting issues with the Context Menu Proxy is different to troubleshooting applications virtualised by Alchemy. When issues occur, the logs go to the Event Viewer instead of the regular Alchemy log file path.

Finding Errors from ContextMenuProxy

If you discover that a context menu is not acting as it should, then the first place you should check is the Event Viewer.

Navigate to Windows Logs > Application and you should hopefully find some error logs. There are a few sources that we should be interested in:

AppAcceleratorV-ExplorerCommandProxyBase: This means an error has occurred in the root node of a Context Menu which implements an IExplorerCommand.

AppAcceleratorV-ExplorerCommandProxySubItem: This means an error has occurred in one of the sub items of a Context Menu which implements an IExplorerCommand.

AppAcceleratorV-ContextMenuProxyBase: This means an error has occurred in a Context Menu which implements an IContextMenu.

AppAcceleratorV-ContextMenuLauncher: This means an error has occurred with the Context Menu Launcher tool (or its 32bit variant).

Finding the Error Message

To find the error message you will need to select the error in Event Viewer and then click on the Details tab.

In the Details tab, you will find a more specific message detailing the error that occurred. Often, it will also log the associated CLSID of the context menu it is trying to virtualise. However, if an error occurs before the Proxy has managed to get access to the CLSID, then it will print the proxy CLSID.

For example, you might get a message like this:

Failed to open registry key for ContextMenuProxy. Result is: 0x0000000 CLSID: {43C545BD-0AE1-4DB9-8D15-090A1578FF01}.

This means that there was an issue with the Proxy CLSID for an IExplorerCommand context menu, and the result code indicates that the registry path can't be found.

From here, we would then check the Cloudhouse root hive to make sure that the Proxy CLSID is mapped to the application's CLSID.

HKEY_LOCAL_MACHINE\SOFTWARE\Cloudhouse\ContextMenuProxy\{43c545bd-0ae1-4db9-8d15-090a1578ff01}.

Error and Status Codes

Where possible, the log messages will contain error or status codes associated to the block of code which has failed. These can be very indicative of the root cause of the issue.

The log message will contain one of the following where possible:

  • Last error code is: {error code}.
  • Result is: {result}.

Last error codes are Microsoft system level codes. You can read more about them in the Microsoft documentation.

Result codes are Microsoft HRESULT codes. You can read more about them in the Microsoft documentation.

Possible Error Messages and Their Meanings

Here is a list of likely error messages, categorized by the area where they can occur:

IContextMenu Only

Error Message Description
Failed to query the selected files The proxy was unable to get data about the selected files. It's possible that an error occurred within Explorer to cause this.
Handled unknown error while initialising An unknown error occurred while initialising the context menu.
Failed to get IContextMenu from out of COM server An error occurred while initialising the original context menu inside of the Launcher. There is likely to be a Launcher error accompanying this error.
Failed to initialise context menu proxy This is an error internal to the Proxy. It has failed to get the base IContextMenu object.
Failed to create instance of IShellExtInit This is an error internal to the Proxy. It has failed to get the base IShellExt object.
Failed to initialise IShellExtInit - probably because Explorer is not looking for a Context Menu This can safely be ignored. Explorer sometimes instantiates IContextMenu DLLs when looking for other object types.
Failed to initialise IShellExtInit This is an error internal to the Proxy. It has failed to initialise the IShellExt object.
Failed to create instance of IContextMenu This is an error internal to the Proxy. It has failed to return the IContextMenu interface.

IExplorerCommand Only

Error Message Description
Failed to get count of shell items There's likely an issue between the Proxy and the virtualised context menu.
Couldn't get item from shell array There's likely an issue between the Proxy and the virtualised context menu.
Failed to get display name from item There's likely an issue between the Proxy and the virtualised context menu.
Failed to initialise explorer command menu proxy There is an error internal to the Proxy. It has failed to intitialise the IExplorerCommand object.
Failed to create instance of IExplorerCommand for the base Proxy This is an error internal to the Proxy. It has failed to create the base IExplorerCommand object.
Failed to create instance of IEnumExplorerCommand for the base Proxy This is an error internal to the Proxy. It has failed to create the base IEnumExplorerCommand object.

Both IContextMenu and IExplorerCommand

Error Message Description
Failed to open registry key for ContextMenu Proxy The proxy was unable to open the key named {CLSID} in the Cloudhouse root {HKLM\HKCU\Software\Cloudhouse\ContextMenuProxy} where {CLSID} is the Proxy CLSID.
Failed to get target CLSID for ContextMenuProxy The proxy was unable to read the CLSID value found in the key mentioned above.
An unexpected error has occurred with {FunctionName} An unexpected error has occurred with a specific function and has been caught by the Proxy.
Failed to initialise Proxy factory This is an error internal to the proxy. It has failed to get the base IFactory object.
CLSID for Context Menu is not registered The CLSID for the context menu we are trying to virtualise is not registered. Perhaps the packager has failed to capture the regpaths.
Failed to get ContextMenuProxy COM Server! Please ensure the binaries are up to date. The Proxy was unable to get an instance.
Failed to launch the Context Menu Launcher, no running objects were found on the ROT This means the Proxy has been unable to launch an instance of ContextMenuLauncher (or its 32bit version) and has also failed to find any COMServer factory objects on the ROT. There is no way to virtualise the context menu.
Waiting for the Context Menu Launcher event timed out The proxy was waiting for the event from ContextMenuLauncher but the wait has timed out. The proxy may still be able to use the Launcher objects regardless. This error would be accompanied by another error if it failed to do so.
Failed to spawn Context Menu Launcher The proxy tool failed to create the ContextMenuLauncher process, the error code sill state why the creation failed.
Failed to spawn Context Menu Launcher, an unexpected error occurred The proxy tool failed to create the ContextMenuLauncher process for an unknown reason.
Failed to get running object table The proxy failed to get access to the ROT.
Failed to enumerate running object table The proxy was unable to enumerate the objects on the ROT.

ContextMenuLauncher

Error Message Description
Failed to create event to indicate ContextMenuLauncher has loaded Events are used when a ContextMenuLauncher process is first launched for the ContextMenuProxy to known when it can start querying data. The Launcher tool has failed to create the event.
Failed to set event to indicate ContextMenuLauncher has loaded Events are used when a ContextMenuLauncher process is first launched for the ContextMenuProxy to know when it can start querying data. The Launcher tool has failed to set the event.
Failed to create instance of COMServer Factory The call to create a COMServer factory has failed.
Exhausted items when searching for IExplorerCommand to invoke A user has clicked on an item which ContextMenuLauncher cannot find to invoke.
Failed to invoke sub level IExplorerCommand A user has clicked on a sub item which ContextMenuLauncher has invoked but returned a failure code.

Quick Things to Check if the Context Menu Fails to Display

If the context menu is failing to display correctly or at all, then go through the following checklist to ensure everything is configured correctly.

  1. Is the application CLSID registered correctly? It should be under the CLSID regpath, check both FileAssociations.xml and in the registry.
  2. Does the application CLSID point to the correct location in the package? Does the DLL exist in that location?
  3. Is the Proxy CLSID registered correctly? It should be under the CLSID regpath, check both FileAssociations.xml and in the registry.
  4. Ensure that the Proxy CLSID points to the correct ContextMenuProxy.dll within the package. It should be in the root package folder.
  5. Is the Proxy CLSID assigned as a context menu with Explorer? It should be under a Shell or ShellEx regpath for a file type association. Check both FileAssociations.xml and in the registry.
  6. Does the root package folder contain the required binaries? The following should all exist in the root path alongisde AppAcceleratorV.exe:
    1. ContextMenuLauncher.exe
    2. 32bitContextMenuLauncher.exe
    3. ContextMenuProxy.dll
Source:
Was this article helpful?

Table of Contents

    Can't find what you're looking for?

    Contact Support