Flow-Launcher/Flow.Launcher · error · Exception
InvokeCommand failed with code {hr:X}
Error message
InvokeCommand failed with code {hr:X} What it means
Thrown when IContextMenu.InvokeCommand returns a non-zero HRESULT while executing the user-selected verb. Unlike errors 20-22 the HRESULT is included in the message (hex), so the verb, item, and failure code are all observable. The verb is passed as an offset (menuItemId - ContextMenuStartId); a wrong offset or a verb the item does not implement is the usual cause.
Source
Thrown at Plugins/Flow.Launcher.Plugin.Explorer/Helper/ShellContextMenuDisplayHelper.cs:221
contextMenu.QueryContextMenu(hMenu, 0, ContextMenuStartId, ContextMenuEndId, (uint)ContextMenuFlags.Explore);
var directory = Path.GetDirectoryName(fileName);
var invokeCommandInfo = new CMINVOKECOMMANDINFO
{
cbSize = (uint)Marshal.SizeOf(typeof(CMINVOKECOMMANDINFO)),
fMask = (uint)ContextMenuInvokeCommandFlags.Unicode,
hwnd = IntPtr.Zero,
lpVerb = (IntPtr)(menuItemId - ContextMenuStartId),
lpParameters = null,
lpDirectory = null,
nShow = 1,
hIcon = IntPtr.Zero,
};
hr = contextMenu.InvokeCommand(ref invokeCommandInfo);
if (hr != 0)
{
throw new Exception($"InvokeCommand failed with code {hr:X}");
}
}
finally
{
if (hMenu != IntPtr.Zero)
DestroyMenu(hMenu);
if (contextMenu != null)
Marshal.ReleaseComObject(contextMenu);
if (pContextMenu != IntPtr.Zero)
Marshal.Release(pContextMenu);
if (shellFolder != null)
Marshal.ReleaseComObject(shellFolder);
if (pShellFolder != IntPtr.Zero)
Marshal.Release(pShellFolder);View on GitHub (pinned to 7fc63b07bb)
Solutions
- Use CMINVOKECOMMANDINFOEX with the verb *name* (lpVerbW) and the CMIC_MASK_UNICODE flag instead of an integer offset to survive menu reordering.
- Pass a real HWND (the Flow Launcher main window handle) so prompts and elevation dialogs have an owner.
- Translate the common HRESULTs (E_INVALIDARG, E_ACCESSDENIED, CO_E_CLASSSTRING) into user-facing messages.
- Rebuild the menu right before invoking if any time has elapsed since GetContextMenuWithIcons was called.
Example fix
// before
lpVerb = (IntPtr)(menuItemId - ContextMenuStartId),
...
hr = contextMenu.InvokeCommand(ref invokeCommandInfo);
if (hr != 0) throw new Exception($"InvokeCommand failed with code {hr:X}");
// after - pass verb by name and own HWND
var info = new CMINVOKECOMMANDINFOEX {
cbSize = (uint)Marshal.SizeOf(typeof(CMINVOKECOMMANDINFOEX)),
fMask = (uint)(ContextMenuInvokeCommandFlags.Unicode | ContextMenuInvokeCommandFlags.FlagNoUi),
hwnd = mainWindowHandle,
lpVerbW = verbName,
nShow = 1,
};
hr = contextMenu.InvokeCommand(ref Unsafe.As<CMINVOKECOMMANDINFOEX, CMINVOKECOMMANDINFO>(ref info));
if (hr != 0) throw new COMException($"InvokeCommand failed for verb '{verbName}'", hr); Defensive patterns
Strategy: try-catch
Validate before calling
if (menuItemId < ContextMenuStartId || menuItemId > ContextMenuEndId)
throw new ArgumentOutOfRangeException(nameof(menuItemId)); Type guard
static bool IsValidMenuId(uint id) => id >= 0x0001 && id <= 0x7FFF;
Try / catch
try { ShellContextMenuDisplayHelper.ExecuteContextMenuItem(fileName, menuItemId); }
catch (Exception ex) when (ex.Message.StartsWith("InvokeCommand failed"))
{
var hr = ParseHResultFromMessage(ex.Message);
App.API.ShowMsgError($"Action could not be performed (0x{hr:X}).");
} Prevention
- Invoke verbs by name (CMINVOKECOMMANDINFOEX.lpVerbW), not by integer offset.
- Pass a real HWND so elevation/owner prompts work.
- Rebuild the menu right before invoking to avoid stale offsets.
- Map common HRESULTs to user-facing messages.
When it happens
Trigger: The menuItemId was captured from a stale menu built against a different file, so the offset points at the wrong verb; the underlying verb handler (shell extension) returned an error; the verb requires a parent HWND (lpVerb window owner) but hwnd is IntPtr.Zero so a UAC/owner prompt fails; the file was deleted between menu construction and invocation.
Common situations: User opened the menu, deleted the file in another app, then clicked the verb; an elevation-requiring verb (e.g. 'run as administrator') fails because the host window is not supplied; a 32-bit shell extension is loaded into a 64-bit process or vice-versa; antivirus blocked the operation and the verb handler returned E_FAIL.
Related errors
- SHParseDisplayName failed
- SHBindToParent failed
- GetUIObjectOf failed
- Failed to delete HBitmap.
- Failed to get the desktop shell folder
AI-assisted analysis of Flow-Launcher/Flow.Launcher@7fc63b07bb (2026-08-13).
Data as JSON: /api/errors/2c50496d2b4a5484.
Report an issue: GitHub.