Click here to Skip to main content
Click here to Skip to main content
Go to top

.NET Shell Extensions - Shell Icon Overlay Handlers

, 14 Sep 2013
Rate this:
Please Sign up or sign in to vote.
Create Shell Icon Overlay Handlers using .NET!
Introduction  

Shell Icon Overlay Handlers can be really useful. They let you display an icon overlay over shell objects to provide extra information. Programs like Dropbox use these overlays to show whether icons are synchronised or not. In this article, I'll show you how to use SharpShell to create Shell Icon Overlay Handlers in no time at all!

Below is a screenshot of the sample we'll create - it shows a padlock over files that are read-only. 

Above: Some text files in a folder. With this shell icon extension installed, read-only files have a padlock overlay.  

The Series  

This article is part of the series '.NET Shell Extensions', which includes:

  1. .NET Shell Extensions - Shell Context Menus  
  2. .NET Shell Extensions - Shell Icon Handlers  
  3. .NET Shell Extensions - Shell Info Tip Handlers     
  4. .NET Shell Extensions - Shell Drop Handlers   
  5. .NET Shell Extensions - Shell Preview Handlers   
  6. .NET Shell Extensions - Shell Icon Overlay Handlers
  7. .NET Shell Extensions - Shell Thumbnail Handlers
  8. .NET Shell Extensions - Shell Property Sheets    

Getting Started  

Shell Extensions are normally written in C or C++. Until the .NET Framework 4 was released, it was not possible to reliably create a Shell Extension using .NET. Now you can. With the SharpShell library, all of the COM plumbing is handled for you, and you simply have to create a class for the extension, decorate it with some attributes and override some functions.

To show how easy this is, let's see the full code for the read-only file icon overlay handlers. 

Our Goal 

Here's the full code for the read-only overlay handler. It's very lean indeed - now that we've seen it in full, I'll describe how to create your own extension step-by-step. 

/// <summary>
/// The ReadOnlyFileIconOverlayHandler is an IconOverlayHandler that shows
/// a padlock icon over files that are read only.
/// </summary>
[ComVisible(true)]
public class ReadOnlyFileIconOverlayHandler : SharpIconOverlayHandler
{
    /// <summary>
    /// Called by the system to get the priority, which is used to determine
    /// which icon overlay to use if there are multiple handlers. The priority
    /// must be between 0 and 100, where 0 is the highest priority.
    /// </summary>
    /// <returns>
    /// A value between 0 and 100, where 0 is the highest priority.
    /// </returns>
    protected override int GetPriority()
    {
        //  The read only icon overlay is very low priority.
        return 90;
    }
 
    /// <summary>
    /// Determines whether an overlay should be shown for the shell item with the path 'path' and
    /// the shell attributes 'attributes'.
    /// </summary>
    /// <param name="path">The path for the shell item. This is not necessarily the path
    /// to a physical file or folder.</param>
    /// <param name="attributes">The attributes of the shell item.</param>
    /// <returns>
    ///   <c>true</c> if this an overlay should be shown for the specified item; otherwise, <c>false</c>.
    /// </returns>
    protected override bool CanShowOverlay(string path, FILE_ATTRIBUTE attributes)
    {
        try
        {
            //  Get the file attributes.
            var fileAttributes = new FileInfo(path);
 
            //  Return true if the file is read only, meaning we'll show the overlay.
            return fileAttributes.IsReadOnly;
        }
        catch (Exception)
        {
            return false;
        }
    }
 
    /// <summary>
    /// Called to get the icon to show as the overlay icon.
    /// </summary>
    /// <returns>
    /// The overlay icon.
    /// </returns>
    protected override System.Drawing.Icon GetOverlayIcon()
    {
        //  Return the read only icon.
        return Properties.Resources.ReadOnly;
    }
} 

The bulk of this is comments - so you can see, creating overlay handlers with SharpShell is pretty easy!  

Step 1: Creating the Project   

First, create a new C# Class Library project. 

Tip: You can use Visual Basic rather than C# - in this article the source code is C# but the method for creating a Visual Basic Shell Extension is just the same.  

In this example we'll call the project 'ReadOnlyFileIconOverlayHandler'.

Tip: If you add a reference to SharpShell via Nuget, the references below will be added automatically.   

Now add the following references:  

  1. System.Windows.Forms 
  2. System.Drawing 

Rename the 'Class1.cs' file to 'ReadOnlyFileIconOverlayHandler.cs'.

Step 2: Referencing SharpShell   

We now need to add a reference to the core SharpShell library. You can do that in a few different ways:

Add Reference 

Download the 'SharpShell Library' zip file at the top of the article and add a reference to the downloaded SharpShell.dll file.  

Tip: The download on this article is correct at the time of writing - if you need the latest version, use Nuget (as described below) or get the library from sharpshell.codeplex.com.  

Use Nuget 

If you have Nuget installed, just do a quick search for SharpShell and install it directly - or get the package details at https://www.nuget.org/packages/SharpShell.

Use CodePlex 

Rather than getting the library from this page, which may not be the latest version, you can always get the very latest version of the library from CodePlex - on the SharpShell home page which is sharpshell.codeplex.com. Nuget will always have the latest stable version - CodePlex may have betas available, and the CodeProject articles will have the version that was available at the time of writing.   

Step 3: Deriving from SharpIconOverlayHandler   

Now things get interesting. Derive your ReadOnlyFileIconOverlayHandler class from SharpIconOverlayHandler:
/// <summary>
/// The ReadOnlyFileIconOverlayHandler is an IconOverlayHandler that shows
/// a padlock icon over files that are read only.
/// </summary>
public class ReadOnlyFileIconOverlayHandler : SharpIconOverlayHandler

Now we must implement the abstract members of the class. Right click on the SharpIconOverlayHandler part of the line and choose 'Implement Abstract Class'. This will create empty implementations of the functions we need to provide.

 /// <summary>
/// The ReadOnlyFileIconOverlayHandler is an IconOverlayHandler that shows
/// a padlock icon over files that are read only.
/// </summary>
public class ReadOnlyFileIconOverlayHandler : SharpIconOverlayHandler
{
    protected override int GetPriority()
    {
        throw new NotImplementedException();
    }
 
    protected override bool CanShowOverlay(string path, FILE_ATTRIBUTE attributes)
    {
        throw new NotImplementedException();
    }
 
    protected override System.Drawing.Icon GetOverlayIcon()
    {
        throw new NotImplementedException();
    }
}

Here's a description of the functions and how they should be used:

GetPriority 

This function must return the priority of the handler. The priority is used when there are two icon overlays for a single file - the shell will use the icon with the highest priority. Just to be confusing, the highest priority is 0 - the lowest priority is 100.

CanShowOverlay

Every time a shell item will be displayed, this function will be called. The path to the shell item is provided in the path parameter. The FILE_ATTRIBUTE flags are also provided (these are attributes like FILE_ATTRIBUTE_DIRECTORY). Return true if you want the icon overlay to be shown for the specified file.

GetOverlayIcon 

This function must return a standard .NET System.Drawing.Icon object that is the overlay icon to use. 

Step 3: Implement the functions 

Our implementation of these functions is going to be as below. First, GetPriority:

protected override int GetPriority()
{
    //  The read only icon overlay is very low priority.
    return 90;
}

This overlay is useful, but not as important as say, TortoiseSVN's state icons, so let's make the priority low.

Now, CanShowOverlay:

protected override bool CanShowOverlay(string path, FILE_ATTRIBUTE attributes)
{
    try
    {
        //  Get the file attributes.
        var fileAttributes = new FileInfo(path);
 
        //  Return true if the file is read only, meaning we'll show the overlay.
        return fileAttributes.IsReadOnly;
    }
    catch (Exception)
    {
        return false;
    }
} 

We're going to return true (to show the overlay) only if we can get the file attributes without throwing an exception, and if those attributes indicate readonly. (Why don't I use FILE_ATTRIBUTE_READONLY? Well, apparently it doesn't work properly for directories).

The last function, GetOverlayIcon: 

protected override System.Drawing.Icon GetOverlayIcon()
{
    //  Return the read only icon.
    return Properties.Resources.ReadOnly;
}

In the project, I added an icon named 'ReadOnly' to the resources - this just returns it. 

Step 4: Handling the COM Registration     

There are just a few things left to do. First, we must add the COMVisible attribute to our class.  

[ComVisible(true)]
public class ReadOnlyFileIconOverlayHandler : SharpIconOverlayHandler

Next, we must give the assembly a strong name. There are ways around this requirement, but generally this is the best approach to take. To do this, right click on the project and choose 'Properties'. Then go to 'Signing'. Choose 'Sign the Assembly', specify 'New' for the key and choose a key name. You can password project the key if you want to, but it is not required:

 

Debugging the Shell Extension 

The Shell Extension is going to be hosted in Windows Explorer - due to the roundabout way that .NET COM Servers are loaded, it's damn near impossible to get a debugger into the process and step through the managed code. However, there is a way to debug your extension quickly. SharpShell comes with some tools that make working with SharpShell COM servers a bit easier, and one of them is the Server Manager. We can use this tool to debug our extension.  Open up the Server Manager, and load the extension. Choose 'Install' and then 'Register', now open the Test Shell and choose 'Shell Open Dialog' - now breakpoints in you extension should be hit as you move around the file system.

Above: The Server Manager

 

Above: The Test Shell  

Installing and Registering the Shell Extension 

There are a number of ways to install and register SharpShell Shell Extensions. In this section I'll detail them all.  

The regasm Tool

You can use the tool 'regasm' to install and register a shell extension. When using regasm, the shell extension will be installed into the registry (i.e. the Class ID of the COM Server will be put in the COM Server Classes section and associated with the path to the actual server file), it will also register the associations.

The Server Manager Tool 

The Server Manager Tool is my preferred approach for installing/uninstalling and registering/unregistering, at least during development, because it lets you install and register as separate steps. It will also let you specify whether you're installing/uninstalling etc in 32 bit or 64 bit mode.

Manual Registry Manipulation

Generally a bad approach, but if you absolutely have to then the MSDN documentation for Shell Extensions describes the changes that must be made to the registry to manually register a COM server, or a Managed COM Server. The documentation is listed in the 'Useful Resources' section. 

Cheat Sheet 

Here are some useful tips for working with SharpShell and Icon Overlay Handlers.

  • Does it seem like your overlay isn't working? Open regedit and check the path:
    HKLM\Software\Microsoft\Windows\CurrentVersion\Explorer\ShellIconOverlayHandlers  
    Windows supports only a limited number of handlers - in alphabetical order. There may be too many installed.
  • If you need to log events, Run the Server Manager as an Administrator and choose 'Diagnostics > Enable SharpShell Log'. You can now use the functions:
    Log
    LogError
    LogWarning

    in your server class, and these messages will be written to the Windows Event Log (under 'Application').  

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

Dave Kerr
Software Developer
United Kingdom United Kingdom
Follow my blog at www.dwmkerr.com and find out about my charity at www.childrenshomesnepal.org.
Follow on   Twitter

Comments and Discussions

 
QuestionExtract icon PinmemberMayzz4-Feb-14 20:50 
AnswerRe: Extract icon PinmvpDave Kerr9-Feb-14 3:52 
SuggestionMy vote of 5 PinmemberMario Majčica26-Dec-13 12:00 
GeneralRe: My vote of 5 PinmvpDave Kerr30-Dec-13 6:32 
QuestionI have a problem Pinmember11833372@qq.com15-Dec-13 19:50 
AnswerRe: I have a problem PinmvpDave Kerr30-Dec-13 6:36 
QuestionBest Practice for field deployment? [modified] Pinmembergallyjh24-Oct-13 6:58 
AnswerRe: Best Practice for field deployment? PinmvpDave Kerr30-Dec-13 6:37 
Questiondemo doesn´t work PinmemberMember 852817017-Sep-13 0:57 
AnswerRe: demo doesn´t work PinmvpDave Kerr17-Sep-13 1:18 
GeneralDemo works !!! PinmemberMember 852817017-Sep-13 6:37 
GeneralRe: Demo works !!! PinmvpDave Kerr17-Sep-13 10:49 
GeneralMy vote of 5 PinprofessionalPrasad Khandekar14-Sep-13 6:33 
GeneralRe: My vote of 5 PinmvpDave Kerr17-Sep-13 1:18 
QuestionIcon Size and Selection [modified] Pinmemberlcsmneto8-Aug-13 3:11 
AnswerRe: Icon Size and Selection PinmvpDave Kerr8-Aug-13 10:31 
QuestionRe: Icon Size and Selection Pinmemberlcsmneto13-Aug-13 0:46 
AnswerRe: Icon Size and Selection PinmvpDave Kerr13-Aug-13 0:50 
GeneralRe: Icon Size and Selection Pinmemberlcsmneto13-Aug-13 23:21 
GeneralRe: Icon Size and Selection PinmvpDave Kerr15-Aug-13 9:20 
AnswerRe: Icon Size and Selection PinmvpDave Kerr5-Sep-13 0:51 
GeneralMy vote of 5 PinprofessionalAhmed Bensaid12-Jul-13 0:45 
GeneralRe: My vote of 5 PinmvpDave Kerr12-Jul-13 4:55 
QuestionIcon size PinmemberBeerBaron229-Jul-13 23:40 
AnswerRe: Icon size PinmvpDave Kerr10-Jul-13 1:16 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Mobile
Web04 | 2.8.140916.1 | Last Updated 14 Sep 2013
Article Copyright 2013 by Dave Kerr
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid