5

The .NET Shell extension framework called SharpShell is great; I've developed a right-click file Shell ContextMenu "quite easily" that works selecting both files and directories.

Now I would like to develop a Shell ContextMenu by righ-clicking on an empty space (that is, on the Desktop or on a white spot while I'm inside a folder). Is it possible do that still using SharpShell? Or do I need to move to a different solution?... and in 2nd case... what do you suggest?

Thanks

NineBerry
  • 26,306
  • 3
  • 62
  • 93
baru
  • 401
  • 3
  • 9
  • 29

2 Answers2

6

The two solutions presented below work, but in the meantime I have found that there is an easier solution that is actually already used in the samples that come with SharpShell.

See the CopyDirectoryLocationHandler class as an example of a context menu handler that is registered for the directory background (and the desktop):

[ComVisible(true)]
[COMServerAssociation(AssociationType.Class, @"Directory\Background")]
public class CopyDirectoryLocationHandler : SharpContextMenu
{
   // ...
}

If you want the handler to only handle clicks on the desktop background, use this code instead:

[ComVisible(true)]
[COMServerAssociation(AssociationType.Class, @"DesktopBackground")]
public class CopyDirectoryLocationHandler : SharpContextMenu
{
   // ...
}

Old obsolete answer:

You can use SharpShell for this purpose without problem. There are two possible approaches:

  1. Register the Shell Extension to handle the folder background yourself

or

  1. Modify SharpShell to handle the registration of the extension for the folder background for you.

Register the Shell Extension to handle the folder background yourself

Your shell extension is a COM server and as such is identified to the system via a GUID. This GUID is then used at places in the registry to register the COM extension for different purposes. When we manually want to register the extension for a purpose such as extending the context menu for folder backgrounds, it is best when our extension has a fixed GUID.

Currently your class looks like this:

 [ComVisible(true)]
 [COMServerAssociation(AssociationType.Directory)]
 public class MyContextMenuExtension : SharpContextMenu
 {

When compiling, the compiler will automatically generate a GUID to use for that class. But we can specify a specific one to use like this:

 [Guid("A75AFD0D-4A63-41E3-AAAA-AD08A574B8B0")]
 [ComVisible(true)]
 [COMServerAssociation(AssociationType.Directory)]
 public class MyContextMenuExtension : SharpContextMenu
 {

Do not use the same GUID as shown here but create your own unique one in Visual Studio via Menu Tools > Create GUID. Use a different GUID for every shell extension you write.

Then recompile the dll and install and register it again (using regasm or the SharpShell Server Manager tool.

Then create a text file named "registry.reg" with the following content (use your own specific GUID). Instead of "MyContextMenuExtension" specify the name of your extension.

Windows Registry Editor Version 5.00

[HKEY_CLASSES_ROOT\Directory\Background\shellex\ContextMenuHandlers\MyContextMenuExtension]
@="{A75AFD0D-4A63-41E3-AAAA-AD08A574B8B0}"

Install the "registry.reg" file by double clicking. Your extension should now be active when you open the context menu for a folder background or the Desktop.

Instead of using the *.reg file, you can also make the changes manually using registry editor or if you have an installer instruct the installer to make those registry changes.


Modify SharpShell to handle the registration of the extension for the folder background for you

Make the following changes to the SharpShell source code:

In the file AssociationType.cs add a new enum value to the AssociationType enumeration:

  /// <summary>
  /// Create an association to the unknown files class.
  /// </summary>
  UnknownFiles,

  /// <summary>
  /// Create an association to the background of folders and the desktop
  /// </summary>
  DirectoryBackground

In the file ServerRegistrationManager.cs add a new private string constant:

/// <summary>
/// The 'directory' special class.
/// </summary>
private const string SpecialClass_Directory = @"Directory";

 /// <summary>
/// The 'directory background' special class.
/// </summary>
private const string SpecialClass_DirectoryBackground = @"Directory\Background";

Also in the file ServerRegistrationManager.cs in the method CreateClassNamesForAssociations in the big switch statement add a new case like this:

          case AssociationType.Directory:

               //  Return the directory class.
               return new[] { SpecialClass_Directory };

          case AssociationType.DirectoryBackground:

               //  Return the directory background class.
               return new[] { SpecialClass_DirectoryBackground };

Finally you only have to tell your own extension class to use this new enumeration value:

 [Guid("A75AFD0D-4A63-41E3-AAAA-AD08A574B8B0")]
 [ComVisible(true)]
 [COMServerAssociation(AssociationType.Directory)]
 [COMServerAssociation(AssociationType.DirectoryBackground)]
 public class MyContextMenuExtension : SharpContextMenu
 {
NineBerry
  • 26,306
  • 3
  • 62
  • 93
  • 1
    Hint: If you want the menu items to appear only when clicking on the desktop background and not when clicking on the background in normal explorer windows, you can use "DesktopBackground" (without backslash) instead of "Directory\Background" (with backslash) in both solutions mentioned above. – NineBerry Jun 03 '16 at 20:07
  • Thanks! I'm very interesting in your 2nd solution. I have downloaded the [SharpShell source code](https://github.com/dwmkerr/sharpshell/releases), modified code as you suggested and compiled succesfully. But when I try to register my final .dll using the RegAsm command then I get an error `RegAsm: error RA0000: Could not load file or assembly 'SharpShell, Version=2.2.0.0, ...' or one of its dependencies. The located manifest definition does not matchthe assembly reference`. To register it sucessfully I must use the original SharpShell I found inside the Server Manger folder. Any idea? – baru Jun 06 '16 at 09:34
  • See http://stackoverflow.com/questions/215026/the-located-assemblys-manifest-definition-does-not-match-the-assembly-reference. Make sure the system can find your dll. Put it and all required referenced assemblies into the same folder as your shell extension dll or register them in the Global Assembly Cache. – NineBerry Jun 06 '16 at 09:57
  • There is also a "DesktopBackground" class, at least on Windows 10. Please add this to the answer. – Soroush Falahati Apr 05 '17 at 05:35
2

I have used SharpShell some time ago, forgotten it since then (because it works flawlessly). I have used it on files and folders, so your question intrigued me. A little research on the tool led me to the answer No(unfortunately).

The binding is done through the com server associations on SharpShell. And by looking at the documentation of the com server associations I am not seeing the way to your desired functionality.

PS: I encourage you to leave a comment on the documentation page, or contact directly with the author of the library. He seems to be really helpful(I've contacted him before).

Tolga Evcimen
  • 7,112
  • 11
  • 58
  • 91