Search code examples
visual-studio-extensionsvisual-studio-2022

Converting ImageMoniker to WPF BitmapSource in VS2022


I'm developing an extension for Visual Studio that includes a XAML view inside a VS window. I want the extension to look and feel like the native UI. The extension is currently running and working fine in VS2017 and VS2019 using the following code to transform a moniker to a WPF BitmapSource that can be used directly from XAML:

public static BitmapSource GetIconForImageMoniker(ImageMoniker? imageMoniker, int sizeX, int sizeY)
{
    if (imageMoniker == null)
    {
        return null;
    }

    IVsImageService2 vsIconService = ServiceProvider.GlobalProvider.GetService(typeof(SVsImageService)) as IVsImageService2;

    if (vsIconService == null)
    {
        return null;
    }

    ImageAttributes imageAttributes = new ImageAttributes
    {
        Flags = (uint)_ImageAttributesFlags.IAF_RequiredFlags,
        ImageType = (uint)_UIImageType.IT_Bitmap,
        Format = (uint)_UIDataFormat.DF_WPF,
        LogicalHeight = sizeY,
        LogicalWidth = sizeX,
        StructSize = Marshal.SizeOf(typeof(ImageAttributes))
    };

    IVsUIObject result = vsIconService.GetImage(imageMoniker.Value, imageAttributes);

    object data;
    result.get_Data(out data);
    BitmapSource glyph = data as BitmapSource;

    if (glyph != null)
    {
        glyph.Freeze();
    }

    return glyph;
}

This method is a direct copy-paste from the WpfUtil class available in multiple of Mads Kristensen's extensions.

As already mentioned, this works fine in VS2017 and VS2019. Now I want this running in VS2022 as well. The extension shows up inside VS2022 but the icons are no longer shown. The problem is that this returns null in VS2022 but not in the previous versions:

ServiceProvider.GlobalProvider.GetService(typeof(SVsImageService)) as IVsImageService2;

Does anyone know how to make this work in VS2022 as well?


Solution

  • This is caused by changes to the interop libraries in VS2022. Namely, they've all been consolidated to a single library (you can see the details here).

    This does break compatibility with targeting prior versions of Visual Studio. There is a guide for migrating extensions to VS2022, but to summarize, the guidance is to:

    1. Refactor the source code into a Shared Project.
    2. Create a new VSIX projects targeting VS2022 and the VSIX project you have now would remain for targeting prior versions.