Writing Windows Shell Extension Context Menu with Icon in C# 4.0.

Creating Context menu in right-click Windows Explorer is maybe the most frequently asked question in all .NET forums. Also it’s one of the most beneficial and delicious features in desktop programs.

Now Shell extension can be written on .NET 4.0 (Important: you still cannot write shell extensions using any version earlier than .NET Framework 4 because those versions of the runtime do not load in-process with one another and will cause failures in many cases.) with Microsoft All-In-One Code Framework.

As I said in my previous post Microsoft All-In-One Code Framework is a collection of useful .NET samples with good documentation. So it not hard to find good example for this issue:

CSShellExtContextMenuHandler: Shell context menu handler (C#)

VBShellExtContextMenuHandler: Shell context menu handler (VB.NET)

CppShellExtContextMenuHandler: Shell context menu handler (C++)

You can spend just few minutes to understand how it works ( or read in following Jialiang’s blog).

Note: there is small mistake in ReadMe.txt file. If the extension is to be registered on x64, you need to use Visual Studio x64 Win64 Command Prompt, instead of Visual Studio x64 Cross Tool Command Prompt, to register the extension.

However, today I want to show how to write Context Menu with image or icon of your application. You just need to change only QueryContextMenu method.

Listing 1. QueryContextMenu function.

public int QueryContextMenu(

IntPtr hMenu,

uint iMenu,

uint idCmdFirst,

uint idCmdLast,

uint uFlags)


// If uFlags include CMF_DEFAULTONLY then we should not do anything.

if (((uint)CMF.CMF_DEFAULTONLY & uFlags) != 0)


return WinError.MAKE_HRESULT(WinError.SEVERITY_SUCCESS, 0, 0);


// Add a separator.


sep.cbSize = (uint)Marshal.SizeOf(sep);

sep.fMask = MIIM.MIIM_TYPE;


if (!NativeMethods.InsertMenuItem(hMenu, iMenu, true, ref sep))


return Marshal.GetHRForLastWin32Error();


// Use either InsertMenu or InsertMenuItem to add menu items.


mii.cbSize = (uint)Marshal.SizeOf(mii);


mii.wID = idCmdFirst + IDM_DISPLAY;

mii.fType = MFT.MFT_BITMAP;

mii.dwTypeData = menuText;

mii.fState = MFS.MFS_ENABLED;

var bitmap = Resource1.App16_16;

var icon = bitmap.GetHbitmap();

mii.hbmpItem = icon;

if (!NativeMethods.InsertMenuItem(hMenu, iMenu + 1, true, ref mii))


return Marshal.GetHRForLastWin32Error();


// Add a separator.

sep = new MENUITEMINFO();

sep.cbSize = (uint)Marshal.SizeOf(sep);

sep.fMask = MIIM.MIIM_TYPE;


if (!NativeMethods.InsertMenuItem(hMenu, iMenu + 2, true, ref sep))


return Marshal.GetHRForLastWin32Error();


// Return an HRESULT value with the severity set to SEVERITY_SUCCESS.

// Set the code value to the offset of the largest command identifier

// that was assigned, plus one (1).




Where Resource1.App16_16 is the bitmap icon added to resource file.

Hope that it’ll be useful and this post saves your time. And of course, your application now will be more delicious J


7 thoughts on “Writing Windows Shell Extension Context Menu with Icon in C# 4.0.

  1. Pingback: Register Shell Extension Context Menu (also on Windows x64). Part 2. « Artyom Grigor

  2. Nice article! Thank you 🙂

  3. Indeed, thanks Artyom. The All-In-One archive available for download now doesn’t seem to have the *ShellExtContextMenuHandler entries anymore, but there’s a lot there to look through. Thanks for making me aware of it.

  4. Hello bobhood,
    Thanks for your comment!
    I’ve downloaded All-In-One Code Framework (recommended Download) and found CSShellExtContextMenuHandler sample.

  5. This worked great – thanks for the tip! The only issue I had was locating the CSShellExtContextMenuHandler project in the latest release. It exists in the October 2011 downloads.

  6. How to debug a project of this type? A standard F5 does nothing? How can we attach to a process? Thanks

  7. Nice Post
    But I found that you haven’t relased the handle you got from var icon = bitmap.GetHbitmap();
    as you are getting this handle in QueryContextMenu() method.
    Instead of this you need to get the handle in the Constructor and release the same in the destructor.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s