March 11, 2011

Windows Explorer Context Menus

A simple C# function to add context menu items in Explorer
Add a context menu to the Windows Explorer

Use this quick class to add a new menu item to the context menu of folders or file extensions (although I have not tested the latter) in Windows Explorer. Modified from some of the code from the latter article. Could be expanded to add context menu items for different extensions (see first article/link).Have done this but it is not tested.
public class ExplorerContextMenuHelper
{
    private string m_MenuNameSubKey = "MenuName";
    private string m_ExtensionSubkey = "Folder";

    private string m_menuText = "";
    private string m_menuCommand = "";
    private string m_menuCommandLineArgs = "";

    // Some file extension context menu helper
    public ExplorerContextMenuHelper(
            string extension,
            string menuName,
            string menuText,
            string menuCommandLine,
            string menuCommandLineArgs)
        : this(menuName, menuText, menuCommandLine, menuCommandLineArgs)
    {
        Debug.Assert(!string.IsNullOrEmpty(extension));
        m_ExtensionSubkey = extension;
    }

    // Folder context menu helper
    public ExplorerContextMenuHelper(
        string menuName,
        string menuText,
        string menuCommandLine,
        string menuCommandLineArgs)
        : this(menuName, menuText, menuCommandLine)
    {
        Debug.Assert(!string.IsNullOrEmpty(menuCommandLineArgs));
        m_menuCommandLineArgs = menuCommandLineArgs;
    }

    public ExplorerContextMenuHelper(
        string menuName,
        string menuText,
        string menuCommandLine)
    {
        Debug.Assert(!string.IsNullOrEmpty(menuName));
        Debug.Assert(!string.IsNullOrEmpty(menuText));
        Debug.Assert(!string.IsNullOrEmpty(menuCommandLine));
        m_menuText = menuText;
        m_menuCommand = menuCommandLine;
        m_MenuNameSubKey = menuName;
    }


    public ExplorerContextMenuHelper(string menuName)
    {
        Debug.Assert(!string.IsNullOrEmpty(menuName));
        m_MenuNameSubKey = menuName;
    }


    public string ExtensionMenuNameSubKey
    {
        get { return m_ExtensionSubkey + "\\shell\\" + m_MenuNameSubKey; }
    }

    public string ExtensionMenuCommandSubkey
    {
        get { return ExtensionMenuNameSubKey + "\\command"; }
    }

    public string MenuCommand
    {
        get { return m_menuCommand + " " + m_menuCommandLineArgs; }
    }

    public void CheckSecurity()
    {

        //check registry permissions
        RegistryPermission regPerm;
        regPerm = new RegistryPermission(RegistryPermissionAccess.Write,
                    "HKEY_CLASSES_ROOT\\" + ExtensionMenuNameSubKey);
        regPerm.AddPathList(RegistryPermissionAccess.Write,
                    "HKEY_CLASSES_ROOT\\" + ExtensionMenuCommandSubkey);
        regPerm.Demand();

    }

    public bool TryAddMenuItem()
    {
        bool res = false;
        try
        {
            CheckSecurity();
            using (RegistryKey regmenu = Registry.ClassesRoot.
                    CreateSubKey(ExtensionMenuNameSubKey))
            {
                regmenu.SetValue("", m_menuText);
            }
            using (RegistryKey regcmd = Registry.ClassesRoot.
                    CreateSubKey(ExtensionMenuCommandSubkey))
            {
                regcmd.SetValue("", MenuCommand);
            }
            res = true;
        }
        catch (Exception ex)
        {
            LogException(ex.ToString());
        }
        return res;
    }

    public void TryRemoveMenuItem()
    {
        try
        {
            CheckSecurity();
            Registry.ClassesRoot.DeleteSubKey(ExtensionMenuCommandSubkey, false);
            Registry.ClassesRoot.DeleteSubKey(ExtensionMenuNameSubKey, false);
        }
        catch (SecurityException sex)
        {
            LogException(sex.ToString());
        }
        catch (UnauthorizedAccessException uae)
        {
            LogException(uae.ToString());
        }
    }

    private void LogException(string error)
    {
        Debug.WriteLine(error);
    }
}
Here some sample code that uses it:
private void RegisterWithExplorer()
{
  string path = new Uri(Assembly.GetExecutingAssembly().
                        GetName().CodeBase).LocalPath;
  ExplorerContextMenuHelper ecm = new ExplorerContextMenuHelper(
               "PhotoBackupApp", "Backup photos", path, "\"%1\"");
  ecm.TryAddMenuItem();
}

private void UnregisterWithExplorer()
{
  ExplorerContextMenuHelper ecm = new ExplorerContextMenuHelper(
                                                "PhotoBackupApp");
  ecm.TryRemoveMenuItem();
}

No comments: