Porting extensions to Visual Studio 2019

I was recently was trying to use my Visual Studio extension for Antlr in Visual Studio 2019, when I found that it just isn’t working anymore. In fact, I couldn’t even install the extension because it wouldn’t even show up in the search for the plug-in. In fact, there weren’t any extensions available for “Antlr” for Visual Studio 2019! I guess I hadn’t ported the add-in to VS 2019, so I decided to work on that.

Getting it to install in VS 2019

Mads Kristensen says that you only need to change a few things to get an extension that worked in Visual Studio 2017 to work with Visual Studio 2019. That’s simply not true in my case. But, Kristensen’s suggested fixes do take care of the problem of adding the extension to Visual Studio 2019 when the .vsix file is double-clicked. And, it will likely take care of the problem of it not showing up when searching for the extension in VS 2019.

Top-level menus have changed

But, the main problem is an organizational issue. Most extension that I use in VS 2019 have the UI for the extension now appear under the Extensions menu. It is not clear how to do that. The documentation for adding a menu to the Visual Studio menu bar says little about “top-level menus”, except this “Note: In VS 2019, top-level menus contributed by extensions are placed under the Extensions menu.” This, of course, means absolutely nothing because it’s never explained anywhere how to create a top-level menu! In fact, there are only a handful of discussions found via Google Search of IDM_VS_TOOL_MAINMENU, which is a key implementation detail never described.

Starting with the VSSDK Extensibility Samples, Menu and Commands, the code to add a menu to Tools menu is right there and works. However, modifying the .vsct file for the parent menu is not apparent.

<Parent guid="guidSHLMainMenu" id="IDM_VS_MENU_TOOLS"/>

Replacing IDM_VS_MENU_TOOLS with IDM_VS_MENU_EXTENSIONS results in a compiler error:

error VSCT1103: Undefined 'Parent/@id' attribute 'IDM_VS_MENU_EXTENSIONS'
in a <Group> element

Although IDM_VS_MENU_EXTENSIONS is listed as a valid menu in the documentation, I cannot use the constant like the other IDM_VS_MENU_… ID’s.

The solution to adding the menu group to the EXTENSIONS menu is to use IDM_VS_TOOL_MAINMENU.

<Parent guid="guidSHLMainMenu" id="IDM_VS_TOOL_MAINMENU"/>

Managed Extensibility Framework (MEF)

It seems that MEF (aka, unmanageable unextensibility fuck-up) has changed and no longer loads my extension. I’m not exactly sure how to debug this because the MEF Analysis Tool (MEFX) no longer exists. But, it isn’t clear how you use the tool as it’s pretty cryptic. But, it does point to some portions that I can comment out.

Long story short: It turns out I got a little “cut” happy with source.extension.manifest. If your extension uses MEF, do not delete the MEF reference.

    <Asset Type="Microsoft.VisualStudio.MefComponent"
       d:Source="Project" d:ProjectName="%CurrentProject%" 
           Path="|%CurrentProject%|" />

Migrating packages.config to PackageReference

In VS 2019, there is now an option to convert the packages.config to package references within the .csproj file. To do that, I had to upgrade to Net 4.7.2, then navigate to References in the Solution Manager and right-click. It then offered an option to do the migration. Note, if I removed the app.config file, or didn’t do the upgrade to Net 4.7.2, the option to migrate didn’t appear. Afterward, I could then remove the app.config file.

Posted in Tip