Creating Thumbnails Provider Shell Extension for Virtual Drive

The IT Hit User File System Engine provides integrated support for thumbnails that can be displayed in Windows Explorer. Below we will describe how to implement thumbnails shell extension for your Virtual Drive.

The functionality described in this article is available in IT Hit User File System v5 Beta and later versions.

Thumbnails provider shell extension for Virtual File System

You can run your thumbnail handler inside your main app, which processes file system calls, or you can run it in a separate process as a COM exe server or surrogate COM. Running your handler inside your main app provides better performance, even though the difference may not be noticeable in most cases.

Note that unlike context menu on Windows 11, thumbnails handler does not require application identity.

Follow the steps below to implement thumbnails provider shell extension in Windows Explorer:

1. Implement Thumbnails Generator

Implement the IFileSystemItem.GetThumbnailAsync() method and return your thumbnail bitmap:

public async Task<byte[]> GetThumbnailAsync(uint size)
{
    byte[] thumbnail = null;

    string remoteStoragePath = WebDAVDrive.Mapping.MapPath(UserFileSystemPath);
    string pathRemote = ThumbnailGeneratorUrl.Replace("{width}", "" + size);
    pathRemote = filePathRemote.Replace("{height}", "" + size);
    pathRemote = filePathRemote.Replace("{path}", remoteStoragePath);

    using (IWebResponse response = await DavClient.DownloadAsync(new Uri(pathRemote)))
    {
        using (Stream stream = await response.GetResponseStreamAsync())
        {
            thumbnail = await StreamToByteArrayAsync(stream);
        }
    }

    string thumbnailResult = thumbnail != null ? "Success" : "Not Implemented";
    Logger.LogMessage($"Thumbnail: {thumbnailResult}", UserFileSystemPath);

    return thumbnail;
} 

 

2. Create Thumbnails Handler Class

  • If you run the thumbnail handler as COM exe or COM surrogate outside of the main app:

    Derive your thumbnail handler class from ThumbnailProviderHandlerRpcBase class:

    [ComVisible(true)]
    [ProgId("VirtualDrive.ThumbnailProvider")]
    [Guid("05CF065E-E135-4B2B-9D4D-CFB3FBAC73A4")]
    public class ThumbnailProvider : ThumbnailProviderHandlerRpcBase
    {
    }

    The thumbnail handler will find the Engine instance behind the drive on which this thumbnail handler is running automatically and than call the IEngine.GetFileSystemItemAsync() and IFileSystemItem.GetThumbnailAsync() methods when thumbnails is needed.

  • If you run the thumbnail handler as COM exe inside main app:

    Derive your thumbnail provider class from the ThumbnailProviderHandlerIntegratedBase class provided with the Engine and pass your Engine instance directly to the base class constructor: 

    [ComVisible(true)]
    [ProgId("WebDAVDrive.ThumbnailProvider")]
    [Guid("A5B0C82F-50AA-445C-A404-66DEB510E84B")]
    public class ThumbnailProvider : ThumbnailProviderHandlerIntegratedBase
    {
        ThumbnailProvider() : base(Program.Engine)
        {
        }
    }

    The handler will call the Engine instance that you pass to the constructor and than call the IEngine.GetFileSystemItemAsync() and IFileSystemItem.GetThumbnailAsync() methods when thumbnails is needed.

You do not need to implement any methods in your thumbnails handler. 

You must decorate the class with the ComVisibleProgId and unique Guid attributes. You will use them when registering your COM thumbnail handler shell extension. Note that you must create your own unique GUID for your thumbnail provider handler. Do NOT use the GUID from this sample. 

 

3. Register Thumbnail Handler

  • If you are using packaged app or sparse package manifest:

    • If you run the thumbnail handler as COM exe or COM surrogate outside of the main app:

      Add the desktop3:ThumbnailProviderHandler and the com:ExeServer code tags to your packaged app manifest or sparse package manifest:

      <Package 
          xmlns:desktop3="http://schemas.microsoft.com/appx/manifest/desktop/windows10/3"
          xmlns:com="http://schemas.microsoft.com/appx/manifest/com/windows10" ...>
        <Applications>
          <Application ...>
            <Extensions>
              <desktop3:Extension Category="windows.cloudFiles">
                <desktop3:CloudFiles>
                  <desktop3:ThumbnailProviderHandler 
                    Clsid="05CF065E-E135-4B2B-9D4D-CFB3FBAC73A4"/>
                </desktop3:CloudFiles>
              </desktop3:Extension>
              <com:Extension Category="windows.comServer">
                <com:ComServer>
                  <com:ExeServer 
                    DisplayName="VirtualDrive.ShellExtension" 
                    Executable="VirtualDrive.ShellExtension\VirtualDrive.ShellExtension.exe">
                    <com:Class 
                      Id="05CF065E-E135-4B2B-9D4D-CFB3FBAC73A4" />
                  </com:ExeServer>
                </com:ComServer>
              </com:Extension>
            </Extensions>
          </Application>
        </Applications>
      </Package>

      Note that you must specify where your surrogate COM or as your exe COM server is located in com:Extension tag.

    • If you run the thumbnail handler as COM exe inside main app:

      Add just the desktop3:ThumbnailProviderHandler tag:

      <Package 
          xmlns:desktop3="http://schemas.microsoft.com/appx/manifest/desktop/windows10/3"
          xmlns:com="http://schemas.microsoft.com/appx/manifest/com/windows10" ...>
        <Applications>
          <Application ...>
            <Extensions>
              <desktop3:Extension Category="windows.cloudFiles">
                <desktop3:CloudFiles>
                  <desktop3:ThumbnailProviderHandler 
                    Clsid="A5B0C82F-50AA-445C-A404-66DEB510E84B"/>
                </desktop3:CloudFiles>
              </desktop3:Extension>
            </Extensions>
          </Application>
        </Applications>
      </Package>

    Note that in case of a packaged app or sparse package your COM will be automatically registered on app install and deleted on uninstall. You do NOT need to install/uninstall it manually using regsvr32.exe or Win 32 API.

  • If you run COM surrogate and using a regular installer:

    Use the ShellExtensionRegistrar.Register() method or regsvr32.exe or Win 32 API to register your COM.
    ShellExtensionRegistrar.Register()

 

4. Run COM exe Server

If you run your COM exe server (either inside the main app or in a separate process) add the following code to your application:

using (var server = new LocalServer())
{
    server.RegisterClass<ThumbnailProvider>();
    await server.Run();
}

It will allow COM calls to find COM object inside your exe. This step is NOT required in case of a surrogate COM.