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

  1. Use CMINVOKECOMMANDINFOEX with the verb *name* (lpVerbW) and the CMIC_MASK_UNICODE flag instead of an integer offset to survive menu reordering.
  2. Pass a real HWND (the Flow Launcher main window handle) so prompts and elevation dialogs have an owner.
  3. Translate the common HRESULTs (E_INVALIDARG, E_ACCESSDENIED, CO_E_CLASSSTRING) into user-facing messages.
  4. 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

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


AI-assisted analysis of Flow-Launcher/Flow.Launcher@7fc63b07bb (2026-08-13). Data as JSON: /api/errors/2c50496d2b4a5484. Report an issue: GitHub.