Shell Extensions - Context Menu
I couldn’t blog for long time due to some personal reasons. Hope I’ll be able to blog without any breaks in future. I'm going to write something different this time, Context Menu for explorer.
I wanted to write a context menu extension for the explorer using some Win32 API calls, which took me a while and it was really a pain. Had problems in debugging, needed to reboot the machine number of times, etc… So thought of coming up with a wrapper in .NET. The wrapper is mainly an abstract class which can be driven to create a personalized context menu extension. The assembly can be downloaded from here and the source can be downloaded from here.
How To use Utils.ShellExtensions.ContextMenu.dll
Deploy Utils.ShellExtensions.ContextMenu.dll in gac. Create a class library project. Add Utils.ShellExtensions.ContextMenu.dll to your project. Drive a class from BaseContextMenu. Make it com visible, install it in gac and register it for com.
Example

[ComVisible(true), Guid("0056DA96-FFD6-4180-BAB2-8C9B6F552B2D")]
public class MyMenu : BaseContextMenu
{
[ComRegisterFunction]
public static void RegisterFunction(Type t)
{
//Register for files
RegisterContextMenu.Register("*", t.GUID);
//Register for folders
RegisterContextMenu.Register("Directory", t.GUID);
//Register for drives
RegisterContextMenu.Register("Drive", t.GUID);
}
[ComUnregisterFunction]
public static void UnregisterFunction(Type t)
{
RegisterContextMenu.Unregister("*", t.GUID);
RegisterContextMenu.Unregister("Directory", t.GUID);
RegisterContextMenu.Unregister("Drive", t.GUID);
}
public override void AssembleMenu()
{
System.Drawing.Bitmap bmp = new System.Drawing.Bitmap(@"c:\test.bmp");
System.Drawing.Bitmap bmp1 = new System.Drawing.Bitmap(@"c:\test1.bmp");
MenuItems menuItems1 = new MenuItems("Test1",0,false);
MenuItems menuItems2 = new MenuItems("Test2",1,false,bmp,true);
MenuItems menuItems3 = new MenuItems("Test3",2,false,bmp1,false);
menuItems2.Click +=new Utils.ShellContextMenu.MenuItems.MenuClickHandler(menuItems2_Click);
menuItems3.Click +=new Utils.ShellContextMenu.MenuItems.MenuClickHandler(menuItems3_Click);
//This order is important. Always insert the parent container and then the child!
InsertMenu(menuItems1);
AddMenu(menuItems1, menuItems2);
AddMenu(menuItems1, menuItems3);
}
private void menuItems2_Click()
{
System.Windows.Forms.MessageBox.Show("Menu Test2 clicked");
}
private void menuItems3_Click()
{
System.Windows.Forms.MessageBox.Show("Menu Test3 clicked");
}
}
I wanted to write a context menu extension for the explorer using some Win32 API calls, which took me a while and it was really a pain. Had problems in debugging, needed to reboot the machine number of times, etc… So thought of coming up with a wrapper in .NET. The wrapper is mainly an abstract class which can be driven to create a personalized context menu extension. The assembly can be downloaded from here and the source can be downloaded from here.
How To use Utils.ShellExtensions.ContextMenu.dll
Deploy Utils.ShellExtensions.ContextMenu.dll in gac. Create a class library project. Add Utils.ShellExtensions.ContextMenu.dll to your project. Drive a class from BaseContextMenu. Make it com visible, install it in gac and register it for com.
Example
[ComVisible(true), Guid("0056DA96-FFD6-4180-BAB2-8C9B6F552B2D")]
public class MyMenu : BaseContextMenu
{
[ComRegisterFunction]
public static void RegisterFunction(Type t)
{
//Register for files
RegisterContextMenu.Register("*", t.GUID);
//Register for folders
RegisterContextMenu.Register("Directory", t.GUID);
//Register for drives
RegisterContextMenu.Register("Drive", t.GUID);
}
[ComUnregisterFunction]
public static void UnregisterFunction(Type t)
{
RegisterContextMenu.Unregister("*", t.GUID);
RegisterContextMenu.Unregister("Directory", t.GUID);
RegisterContextMenu.Unregister("Drive", t.GUID);
}
public override void AssembleMenu()
{
System.Drawing.Bitmap bmp = new System.Drawing.Bitmap(@"c:\test.bmp");
System.Drawing.Bitmap bmp1 = new System.Drawing.Bitmap(@"c:\test1.bmp");
MenuItems menuItems1 = new MenuItems("Test1",0,false);
MenuItems menuItems2 = new MenuItems("Test2",1,false,bmp,true);
MenuItems menuItems3 = new MenuItems("Test3",2,false,bmp1,false);
menuItems2.Click +=new Utils.ShellContextMenu.MenuItems.MenuClickHandler(menuItems2_Click);
menuItems3.Click +=new Utils.ShellContextMenu.MenuItems.MenuClickHandler(menuItems3_Click);
//This order is important. Always insert the parent container and then the child!
InsertMenu(menuItems1);
AddMenu(menuItems1, menuItems2);
AddMenu(menuItems1, menuItems3);
}
private void menuItems2_Click()
{
System.Windows.Forms.MessageBox.Show("Menu Test2 clicked");
}
private void menuItems3_Click()
{
System.Windows.Forms.MessageBox.Show("Menu Test3 clicked");
}
}


25 Comments:
Hey man, thanks for the wrapper. Its a gr8 solution for dot net shell developers. I have a suggestion, Publish your article on codeproject and add some more labels to this blog so that it is easy to be found on google. Thanks Again!!!
Hi Abhiskey,
Thanks. I know that codeproject is welknown to most, but I don't have time now to write an article. I'll do that when I get some free time.
Cheers,
Chester
Hey Chester,
Thanks for the wrapper, i've been struggling to develop my own wrapper for a few days now (based on dinos work) and yours has really helped me solve one or two problems :)
So thanks again!
Happy to know that it helped you. You are welcome!
Chester
It's kind of dangerous to use in-process shell extensions in C#: http://blogs.msdn.com/oldnewthing/archive/2006/12/18/1317290.aspx
But great code :)
One small problem....it crashes Explorer on Vista
I copied the example code and added both the utils library and my newly created library to the GAC.
I can't seem to register the dll file, Im trying to run regsvr32 but to no avail.
can someone please help me out here?
You need to install it into GAC (using gacutil) and then register it for com (using regasm).
Hi Chester,
Great work.
Do you know how to install it in Installshield? I'm having hard time with it.
It installs it to the GAC and creates registry entries but doesn't work.
Thanks
Hi,
Thanks. I haven't used Installshield before to install in GAC but heard people saying it’s hard to install using it. I've created an installer for a small project for the above one using VS.NET install solution. It was pretty simple and easy. If you are interested, please mail me (chestermr@gmail.com). I’ll mail you the solution.
Cheers,
Chester
I hope I'm not missing something obvious... Is there a way to know the file/folder that was clicked on in the event handler? Thanks.
I’m not a coder, but your information was interesting for me as a user.
Thank You!
It doesn't work on my Vista x64, moreover it deletes all non-standard entries in explorer context menu such as WinRAR...
please help
Seriously, how do we know what file was clicked?
Bill
Hi Chester,
Thanks for the wrapper, will it support x64 architecture.
Thanks
Mani
Hi Chester,
Thanks for the wrapper. Is it support x64 architecture?
Thanks in advance.
How do i know which file(s) or directory has been clicked in the event handler?
I had downloaded the Assemble and source but i haven't go any such Utils.ShellExtensions.ContextMenu.dll.
Pls help me.
The download links are no longer working. Visit
http://code.msdn.microsoft.com/ShellContextMenuExte
Hi Chester, Great Work
Please let me know how to add a context menu item to a perticular files not all files. That is my urgent requirement struggling plz help me.
Thanks in Advance
Narayana Rao
Could you perhaps post the files again? The URLs no longer work.
Hi,
I have tried to add a context menu using Utils.ShellExtensions.ContextMenu.dll. First i have added this dll in GAC. I have create a class library project and add code just like the instruction that i found from the link "http://chestermr.blogspot.com/2007/03/shell-extension-context-menu.html". Also i have follow all of the instruction. And i have seen the registry that my GUID is install. But problem is when i right click on a file there is no menu found that i have created. Please give a solution. Its urgent. Or give a sample source code that use above this dll for Creating Context Menu.
BR,
Sazzad
Hi,
I understand how get name file or folder if AllowMultiSelect = false.
uint nSelected = Win32.DragQueryFile((IntPtr)drop, 0, sbFile, (uint)sbFile.Capacity + 1);
string object_name = sbFile.ToString();
But i don't understand how i can get all names selected files or folders (if AllowMultiSelect = true).
I obtained results:
StringBuilder fileList = new StringBuilder();
StringBuilder sb = new StringBuilder(1024);
uint i = 0;
//Get number of files
uint uNumFiles = 0;
uNumFiles = DllImports.DragQueryFile(m_hDrop, 0xFFFFFFFF, null, 0);
//make file name
while (i < uNumFiles)
{
DragQueryFile(m_hDrop, i, sb, sb.Capacity + 1);
fileList.Append(sb + ",");
i++;
}
Did any body resolve the Vista issue? its crashing in Vista and Windows 7.
Thanks
Saket
Post a Comment
<< Home