1

I'm trying to implement custom overlay icons for my app. Here's the (simplified) code:

[ComVisible(true)]
[Guid("30BD35BE-D5CE-4751-A3B3-9D601F926E36")]
public abstract class OverlayIconBase : IShellIconOverlayIdentifier
{
    private const string OverlayIdentifiersKeyPath = @"SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\ShellIconOverlayIdentifiers";
    private readonly string _iconFileName;
    protected OverlayIconBase()
    {
        _iconFileName = GetType().Assembly.Location;
    }

    protected static void Register(Type type, string registrationName)
    {
        string guid = type.GUID.ToString("B").ToUpper();

        string keyPath = OverlayIdentifiersKeyPath + "\\" + registrationName;
        using (var key = Registry.LocalMachine.CreateSubKey(keyPath))
        {
            key.SetValue(string.Empty, guid);
        }

        NativeMethods.SHChangeNotify(SHChangeNotifyEvents.AssocChanged, SHChangeNotifyFlags.IdList, IntPtr.Zero, IntPtr.Zero);
    }

    protected static void Unregister(Type type, string registrationName)
    {
        string keyPath = OverlayIdentifiersKeyPath + "\\" + registrationName;
        Registry.LocalMachine.DeleteSubKeyTree(keyPath, false);

        NativeMethods.SHChangeNotify(SHChangeNotifyEvents.AssocChanged, SHChangeNotifyFlags.IdList, IntPtr.Zero, IntPtr.Zero);
    }

    public int IsMemberOf(string path, uint attributes)
    {
        try
        {
            return ShouldDisplay(path) ? WinError.S_OK : WinError.S_FALSE;
        }
        catch
        {
            return WinError.E_FAIL;
        }
    }

    public int GetOverlayInfo(IntPtr pwszIconFile, int cchMax, out int iconIndex, out uint flags)
    {
        iconIndex = 0;
        flags = 0;
        if (string.IsNullOrEmpty(_iconFileName) || fileName.Length + 2 > cchMax)
            return WinError.E_FAIL;

        int count = Encoding.Unicode.GetByteCount(_iconFileName);
        byte[] bytes = new byte[count + 2];
        Encoding.Unicode.GetBytes(_iconFileName, 0, _iconFileName.Length, bytes, 0);
        Marshal.Copy(bytes, 0, pwszIconFile, bytes.Length);
        iconIndex = IconIndex;
        flags = (uint) (ShellIconOverlayIdentifierFlags.ISIOI_ICONFILE | ShellIconOverlayIdentifierFlags.ISIOI_ICONINDEX);
        return WinError.S_OK;
    }

    public int GetPriority(out int priority)
    {
        priority = Priority;
        return WinError.S_OK;
    }

    // 0-100 (0: highest); typically 0
    protected virtual int Priority { get { return 0; } }

    protected abstract bool ShouldDisplay(string path);
    protected abstract int IconIndex { get; }
}

[ComVisible(true)]
[Guid("76344480-04C1-4D15-A0A5-578881CEF415")]
public class MyOverlayIcon1 : OverlayIconBase
{
    private const string RegistrationName = "MyOverlayIcon1";

    [ComRegisterFunction]
    static void Register(Type t)
    {
        Register(t, RegistrationName);
    }

    [ComUnregisterFunction]
    static void Unregister(Type t)
    {
        Unregister(t, RegistrationName);
    }

    protected override bool ShouldDisplay(string path)
    {
        /* some logic to decide if the overlay should be displayed... */
    }

    protected override int IconIndex
    {
        get { return 0; }
    }
}

The icons are embedded in the DLL using Win32Res as explained here.

By attaching to explorer.exe with Debugger.Launch, I was able to confirm that GetOverlayInfo and IsMemberOf work as expected, however the overlay is not displayed in the explorer.

What could be the problem?

Thomas Levesque
  • 286,951
  • 70
  • 623
  • 758

1 Answers1

2

You are probably running into a similar issue to what is talked about in this thread. Tortoise-svn icons not showing up under windows 7

Community
  • 1
  • 1
Matthew Brubaker
  • 3,097
  • 1
  • 21
  • 18
  • Yep, that seems to be the reason... I was also using TortoiseSVN (9 overlays) and DropBox (4 overlays), so I was hitting the limit. Thanks! – Thomas Levesque Oct 02 '12 at 14:10