Continuing with the series of articles to show how to do things in a native way in a Visual Studio package instead of using the automation model (EnvDTE), in this new article I show how to get the solution events using the IVsSolutionEvents interface. As I expected, it is more difficult than using the automation model, with more code, and even requires you to use a cookie!:
HOWTO: Get solution events from a Visual Studio package
MSDN documentation about VSX has improved a lot in the past years and now you have HOWTO examples, walkthroughs, etc. However, it seems to me that it still needs improvement in some areas such as navigation and attention to the details. For example, if you read the topics on VSIX deployment, you will find links to a subject “PAVE Visual Studio Extension Deployment.”:
Apart that nobody knows what “PAVE” means, it happens that the links are broken and you get “We’re sorry—the topic that you requested is no longer available.”:
However, if you select Visual Studio 2010 in the Other Versions dropdown you get the content:
And the lack of attention or care that I mentioned: this was reported months ago and nobody has fixed it:
An issue that I noticed some weeks ago when playing with packages in several Visual Studio versions was that in VS 2010 command menus were not updated after a change in the .vsct file just clicking F5 to start debugging, I had to rebuild. However, in VS 2012/2013 it just worked without an explicit rebuild action.
In this new article I provide a repro scenario and a fix that involves updating a MSBuild target of the VS 2010 SDK to behave like the ones of VS 2012/2013 SDKs:
PRB: Menu commands not refreshed after a change when clicking Start Debugging in a VS 2010 package project
I have written this article to show how to provide the bitmaps for commands from embedded resources of the assembly, rather than from files on disk (the default):
HOWTO: Provide command bitmaps from embedded resources of a Visual Studio package.
Since one of the goals of this site is to contain links to every VSX-related useful piece of information out there, I have added in the Articles section about packages some old (2009-2010) blogs posts about VSIX and Pkgdef files. They are still relevant today and are the following:
I am these days porting my MZ-Tools add-in to a package, and as every other developer of extensions I would like to target several different Visual Studio versions (say 2010, 2012 and 2013 and “14”) with:
- The same project file (MyAssembly.csproj)
- The same binary assembly (MyAssembly.dll)
- The same setup (MyAssembly.vsix or MyAssemblySetup.exe)
About #1, you need to learn something about MSBuild but is doable. In my case I just want to use VS 2013 always and changing something in the .csproj file I can deploy and debug selectively to VS 2010, 2012 or 2013 experimental instances. But if you want to change nothing, you can open the same .csproj file in different VS versions and deploy and debug for that VS version as Daniel Cazzulino explained in his post How to create a Visual Studio extensibility project that is compatible with VS 2010, 2012 and 2013. Jared Parsons has also explained about Round Tripping a VSIX project.
About #2, if you stick to the assemblies provided by VS 2010 that are also supplied by higher VS versions it is doable too. I have used that approach for MZ-Tools being an add-in for years, as I explained in the article HOWTO: Create an add-in that targets several Visual Studio versions with the same add-in DLL using C# or VB.NET.
About #3, .vsix files already have support for several Visual Studio versions specified in the manifest. And if you create your own setup (MSI or otherwise) you have full control of the deployment.
As you know, whether you are an add-in developer or a package developer, Visual Studio calls your package or add-in to query the status of your commands when it requires to know it, for example, before showing the menu items of a menu, when the selected object has changed, etc. However, in rare occasions you may need to tell Visual Studio that you want it to query the status of your commands. A user of the MSDN VSX forum has asked it today, for example.
I was somewhat familiar with the solution for add-ins, which is to use the UpdateCommandUI method of the EnvDTE80.Commands2 interface (notice that the EnvDTE.Commands interface lacks that method, so you need to cast DTE.Commands to EnvDTE80.Commands2). Reviewing the code of my MZ-Tools add-in, certainly I needed to use it for a integration test.
I was also somewhat familiar with the solution for packages because I found the UpdateCommandUI method of the IVsUIShell by chance some time ago just perusing the MSDN documentation.
While migrating my MZ-Tools add-in to a package, I found an issue: I wanted a button to be initially invisible on my toolbar. By “initially” I mean before the package is loaded, that is, declaring the invisibility in the .vsct file using:
However, the button appeared initially disabled rather than invisible. Investigating I found this reported in the MSDN VSX forum as back as in 2006 (VS 2005 I guess) using the old .ctc file rather than the new .vsct file and, guess what, that behavior is “by design”. However, buttons on toolwindows toolbars (rather that on IDE toolbars) can be initially invisible.
I created a sample package to reproduce the problem. The package creates two commands (the first one initially invisible) that are placed in three locations: the Tools menu, the Standard toolbar and the Solution Explorer toolbar. Notice that the button on the Standard toolbar is disabled rather than invisible:
And I have documented this behavior with code in this article:
PRB: Button of package command cannot be initially invisible on Visual Studio toolbar
Another very confusing thing when starting with packages and you have a background of creating add-ins is how to name a command.
With add-ins, the (full) name of a command was composed by two parts:
And one interesting consequence was that all the commands of your add-in used the same prefix. With packages this is not true. The prefix of a command created by a package follows some complicated rules that depend on the menu / toolbar / context menu where the command is mainly placed (because, you know, a command is not a UI item and you can create several UI items in different locations tied to the same command).
And even the (short) name of the command can vary depending on the values of <CommandName>, <LocCanonicalName> and, go figure, can even be inferred from the caption of the command (<ButtonText>) removing special characters, etc.
I have written this article to try to explain all rules:
INFO: How a Visual Studio package command is named
One of the most confusing things when starting with packages and you have a background of creating add-ins is how to create and name commands, which are not user interface items.
With add-ins, commands are created by code, and there are two separate steps: one to create the command (Commands2.AddNamedCommand2 method) and other step to create UI items (either temporary or permanent) such as menu items, toolbar buttons, etc. See:
HOWTO: Adding buttons, commandbars and toolbars to Visual Studio .NET from an add-in.
However, commands in packages are created by declarations in a .vsct file, and the separation between command and UI items is very blurry (and how to name a command is a subject for another post). For example, you have a <Commands> section, but commands are actually declared inside a <Buttons> section using <Button> elements. I can’t insist enough that in Visual Studio a command is not a button (or a menu item), and, in fact, sometimes your extension may want to provide a command without a user interface item. For example, if you want the command to be executed by default only with a keyboard shortcut. Or for some reason you need an “internal” command. My MZ-Tools add-in does this with at least one command.
So, I have written this article to show how you would create a command in a package without UI items:
HOWTO: Create a command without user interface items from a Visual Studio package