Category Archives: MZ-Tools Articles Series

MZ-Tools Articles Series: HOWTO: Get a CommandBar by Guid and Id rather than by name from a Visual Studio add-in

Getting a Visual Studio built-in commandbar to add buttons to it is not so easy as it may seem. You have the DTE.CommandBars collection, but:

– To retrieve a commandbar by name, you have to guess its name first. See: HOWTO: Guessing the name of a command bar to add a custom menu entry in Visual Studio .NET add-ins

– If the commandbar is not a “root” commandbar, but a commandbar popup, it may not be indexed in that collection, so it is better to get it from the parent CommandBar.Controls collection, but it is not so easy. See: HOWTO: Locate commandbars in international versions of Visual Studio

– Some command bar names are dupplicated.

There is other way to get a commandbar, using its Guid and Id that are truly unique. But this has also some tricks as explained in my latest article:

HOWTO: Get a CommandBar by Guid and Id rather than by name from a Visual Studio add-in
http://www.mztools.com/articles/2011/MZ2011004.aspx

MZ-Tools Articles Series: PRB: COMException 0x80020003 getting events from commandbar popup in Visual Studio 2010

In the old days of VB5/VB6 extensibility which used the Office commandbars model where there weren’t commands (only CommandBarControls) you had to create buttons (CommandBarButton) directly on commandbars, and you had to use the VBE.Events.CommandBarEvents(CommandBarButton) artifact to get the Click event of a CommandBarButton (you couldn’t even get the Click event using the more natural WithEvents clause).

Somehow this strange artifact got in the extensibility of the new Visual Studio .NET 2002 IDE (likely because it still used the Office commandbar model). However, in Visual Studio you have commands (EnvDTE.Command) and the recommended way is to create CommandBarButtons from commands (Command.AddControl), not directly on commandbars without a command (CommandBar.Controls.Add), and rather than getting a Click event when a CommandBarButton is clicked, you get a method (IDTCommandTarget.Exec) called when the command is executed. So, DTE.Events.CommandBarEvents is no longer necessary. There is still an scenario where you may want to create a CommandBarButton without an underlying command, for example the context menu of a listview of a toolwindow of an add-in, where you want the look and feel of the Visual Studio menus so you use a CommandBarPopup, but you don’t want commands. However, in this scenario you can use the Click event of the CommandBarButton class, without using DTE.Events.CommandBarEvents.

But people were still using DTE.Events.CommandBarEvents for another case: to know when a CommandBarControl which is a CommandBarPopup is clicked just before showing the children CommandBarButtons, presumably to set its state (enabled, disabled, invisible, etc.). Well, it happens that the new WPF-based commandbars of Visual Studio 2010 break that case, and this has caused some inconvenience to some people.This new article documents this problem:

PRB: COMException 0x80020003 getting events from commandbar popup in Visual Studio 2010
http://www.mztools.com/articles/2011/MZ2011003.aspx

Fortunately the remedy is easy: use the IDTCommandTarget.QueryStatus method:

HOWTO: Controlling the state of command in a Visual Studio add-in
http://www.mztools.com/articles/2007/MZ2007025.aspx

MZ-Tools Articles Series: PRB: NotImplementedException adding a solution folder to a solution folder in Visual Studio from a macro or add-in

This new small article of the MZ-Tools Articles Series documents a problem that happens creating a solution folder (VS 2005 or higher) belonging to an existing solution folder, that was reported in the MSDN VSX Forum and it was reported on the web long time ago too:

PRB: NotImplementedException adding a solution folder to a solution folder in Visual Studio from a macro or add-in
http://www.mztools.com/articles/2011/MZ2011002.aspx

I wouldn’t say it is a bug because a NotImplementedException is normally “by design” but anyway I have reported it to Microsoft Connect and maybe it is implemented or fixed in next Visual Studio versions:

Microsoft Connect: NotImplementedException adding solution folder to solution folder
https://connect.microsoft.com/VisualStudio/feedback/details/635048/notimplementedexception-adding-solution-folder-to-solution-folder

A possible workaround would be to create the child solution folder belonging to the solution too, and then drag and drop it over the first solution folder, but drag and drop operations can’t be done using the automation model (EnvDTE).

Update (Dec 3, 2013): see this new post with a full workaround

MZ-Tools Articles Series: HOWTO: Create a solution from a Visual Studio add-in.

I have always found creating solutions using the automation model (EnvDTE) somewhat tricky, because there are two phases: creating the solution and saving the solution to disk, and the methods used to do that are confusing:

– It happens that you have a Solution.Create method, which one would expect to receive only the name of the solution in the Solution Explorer (which is also the base name for the .sln file), but it receives the folder of the solution too, although this method doesn’t save the solution file (.sln) on disk (so, why does it need the folder of the solution?).

– You have also the Solution.SaveAs method, which receives as parameter the name of the .sln file with path, two (combined) pieces of information that you already specified in the Solution.Create method. One would expect a Solution.Save method without parameters. It happens that you have the Solution.Saved property, which is read/write, but I am not sure if you can save the solution setting its value to true.

– Finally, the folder of the solution must exist. Visual Studio doesn’t bother to create it (why?). At least the example of the documentation about Solution2.Create and Solution3.Create warns you, but there is no example if you fall in the SolutionClass.Create or _Solution.Create help pages.

– The confusion is such that the MSDN documentation about the Solution3.Create method lists two “overloaded” methods with the same name and signatures.

I have written the following article which shows also how to get the Visual Studio projects folder, which is the location that you likely want to use to save the solution:

HOWTO: Create a solution from a Visual Studio add-in.
http://www.mztools.com/articles/2011/MZ2011001.aspx

MZ-Tools Articles Series: PRB: Unable to add buttons to toolbars of toolwindows of Visual Studio from an add-in

Today there was a question in the MSDN Forum for Visual Studio Extensibility (VSX) about adding a button to the toolbar (not to the context menu) of the Solution Explorer from a Visual Studio add-in. This is something that I am interested in too from time to time because I would like to move the “Collapse Projects” button of my MZ-Tools 6.0 add-in from the toolbar of the add-in to the more natural place, the toolbar of the Solution Explorer. I tried almost five years ago, when Visual Studio 2005 introduced EnvDTE80 and the new EnvDTE80.Window2 with its CommandBars property that gives you access to the toolbar of a toolwindow. Since add-ins are second-class citizens, this scenario was not tested by Microsoft and I found a bug that I reported:

COMException removing button from Solution Explorer commandbar
https://connect.microsoft.com/VisualStudio/feedback/details/113953/comexception-removing-button-from-solution-explorer-commandbar

The bug occurred actually removing the button, not adding it, but as Microsoft explained:

“It turns out the bug here is actually in the code to add the control, not delete it. The Solution Explorer toolbar has an internal flag indicating that modifications should not be allowed; CommandBarControl.Delete is properly respecting that flag (hence the error) but Command.AddControl is not.”

and when they finally fixed this problem (in VS 2008), it was not allowing add-ins to add buttons to the Solution Explorer toolbar, but rather throwing a System.UnauthorizedAccessException when you try to do it. Bottom line: add-ins are not allowed to add buttons to the Solution Explorer toolbar. VS 2010 is crystal-clear in its error message that this applies to other toolwindows too. I am not sure if this applies too to packages or only to add-ins.

The details and code to reproduce the problem are in my latest article:

PRB: Unable to add buttons to toolbars of toolwindows of Visual Studio from an add-in
http://www.mztools.com/articles/2010/MZ2010004.aspx

MZ-Tools Articles Series (update for VS 2010) INFO: Default .AddIn file locations for Visual Studio add-ins

I have updated once more one of the most popular articles that I have ever written to include information about Visual Studio 2010:

INFO: Default .AddIn file locations for Visual Studio add-ins
http://www.mztools.com/Articles/2008/MZ2008001.aspx

This is a problematic area in Visual Studio extensibility that is increasingly complicated with each new Visual Studio version or Windows version:

– Actual folder names changed between Windows XP and Windows Vista (fortunately Windows 7 doesn’t change them).

– Folders can be localized.

– If Visual Studio 2005 provided 5 folders (too many) where to search for .AddIn files, Visual Studio 2008 introduced a 6th one (%ALLUSERSDOCUMENTS%\Microsoft\MSEnvShared\AddIns), which actually never worked.

Visual Studio 2010 has fixed that bug with the 6th folder introduced by VS 2008, but Microsoft couldn’t resist to introduce a new (the 7th!) folder: %ALLUSERSPROFILE%\Microsoft Visual Studio\Addins (which at least works on its debut).

Furthermore, the long standing bug about the “Application Data” part hardcoded in one of the locations(%ALLUSERSPROFILE%\Application Data\Microsoft\MSEnvShared\AddIns) that I reported and that Microsoft reported that would be fixed, hasn’t been fixed. The fix would be a new folder where “Application Data” is not hardcoded (while keeping the old one to avoid breaking existing add-ins). If the new %ALLUSERSPROFILE%\Microsoft Visual Studio\Addins folder is the fix for this problem, it isn’t exactly a fix since it won’t fix add-ins whose setup use CSIDL_COMMON_APPDATA and on Windows XP only work in English.

MZ-Tools Articles Series: HOWTO: Testing add-ins in localized versions of Visual Studio

The third article of the MZ-Tools Articles Series of this year is about testing add-ins in localized (international) versions of Visual Studio. It happens that most developers of the world are either native “English” or use English versions of Visual Studio and/or Windows, and therefore are not 100% aware of localizations that happen in the products. For example, many applications (even from Microsoft) hardcode “Application Data” rather than using the localized version of that folder that Windows uses. See for example this bug in Visual Studio:

Visual Studio hardcodes “Application Data” folder in the list of folders for .AddIn files
https://connect.microsoft.com/VisualStudio/feedback/details/466756/visual-studio-hardcodes-application-data-folder-in-the-list-of-folders-for-addin-files

which causes that setups of add-ins that call the Windows API that returns the actual (localized) name of that folder (the correct thing) actually fail to be recognized as add-ins in non-English versions of Windows, because VS won’t search for .AddIn files in the localized version of the folder (the VS 2008 SDK has an add-in with this problem, for example).

I am Spanish and in my case I use a mix of Spanish/English applications. For example, on same computers I have Windows and Office in Spanish while Visual Studio is in English. Taking into account that Office now offers Visual Studio Tools for Applications (VSTA) and Visual Studio Tools for Office (VSTO) I see issues caused by those mixes sometimes.

I posted a rant about localization issues in Visual Studio long time ago here:

MZ-Tools Articles Series: HOWTO: Get an OutputWindowPane to output some string from a Visual Studio add-in or macro
https://www.visualstudioextensibility.com/2008/08/13/mz-tools-articles-series-howto-get-an-outputwindowpane-to-output-some-string-from-a-visual-studio-add-in-or-macro

and this new article explains how to get multiple localized versions of Visual Studio on the same machine and which areas of an add-in should be tested:

HOWTO: Testing add-ins in localized versions of Visual Studio
http://www.mztools.com/articles/2010/MZ2010003.aspx

MZ-Tools Articles Series: HOWTO: Handle exceptions in a Visual Studio add-in

AFAIK, add-ins can’t use “global” exception handlers using AppDomain.UnhandledException, I think that because maybe all add-ins are loaded in the same AppDomain (not sure) and therefore it wouldn’t be suitable that an add-in handles the unhandled exception of another add-in… Anyway, I use exception handlers all around the code of my MZ-Tools add-in. Although I use a single method to treat the exceptions (showing an error to the user with a “Send Report” button, etc.), I made two errors that I am now (costly) fixing for next versions:

– The bug report misses important information about the IDE where the add-in causes the problem, including the IDE version. While in MZ-Tools 6.0 I use a different add-in assembly for each target IDE (so I can actually know the version), future versions of MZ-Tools will use a single add-in dll to target multiple IDEs.

– That method didn’t receive the DTE object and when I modified it to receive it, I realized that a lot of methods that were trapping exceptions didn’t have that DTE object to pass, because they were “helper” static (shared in C#) methods, so I had to do a lot of refactoring for every method to get access to the DTE object that the Connect class owns.

I have summarized what I consider good practices in this new article:

HOWTO: Handle exceptions in a Visual Studio add-in.
http://www.mztools.com/articles/2010/MZ2010002.aspx

MZ-Tools Articles Series: HOWTO: Locate the index of a CommandBarControl on a Commandbar to add a control or menu before or after it from a Visual Studio add-in.

After three whole months of procrastination about the MZ-Tools Articles Series and a lot of hesitation about continuing or giving up (I am continually struggling with day job, nights/weekends, family, spare time, some needed sport, this blog, the MSDN VSX forum, the MVP program, the MZ-Tools add-in, priorities balancing, etc. and even PS3 Top Spin 3 tennis gaming and a planned switch to Apple / iMac), it seems that today I found some desire to write a new (small) article about a question that appears from time to time in the forums:

HOWTO: Locate the index of a CommandBarControl on a Commandbar to add a control or menu before or after it from a Visual Studio add-in.
http://www.mztools.com/articles/2010/MZ2010001.aspx

More to come about internationalization issues in Visual Studio add-ins that I am facing these days…