Category Archives: Add-Ins

Announcing unified MZ-Tools 8.0 for Visual Studio, VBA (64-bit/32-bit), VB6 and VB5

It has been a long time since my last post here, and for a good reason. Since I released MZ-Tools 8.0 for Visual Studio 2015 last July 1 (converted from add-in to package), I have been very busy the last months to achieve a new huge milestone:

Announcing unified MZ-Tools 8.0 for Visual Studio, VBA (64-bit/32-bit), VB6 and VB5

From the extensibility point of view, MZ-Tools 8.0 is a unique piece in the world, AFAIK: it provides the same feature set for four different IDEs (Visual Studio, VBA editor, Visual Basic 6.0 and Visual Basic 5.0) with different extensibility APIs reusing the same code at binary level:

MZ-Tools 8.0 for Visual Studio (as package):
MZTools8VSPackage

MZ-Tools 8.0 for Visual Studio (as add-in):
MZTools8VSAddIn

MZ-Tools 8.0 for VBA:
MZTools8VBA

MZ-Tools 8.0 for VB6:
MZTools8VB6

MZ-Tools 8.0 for VB5:
MZTools8VB5

As you can see in the images, in all cases there is the same big MZTools8PlugIn.dll file, which contains the feature set, and smaller host adapter dlls that “plug” the features into the IDEs. If you are interested, I outlined the strategy to achieve this in this other post.

MZ-Tools Articles Series: BUG: Visual Studio 2008 crashes if unloaded when an add-in executes DoEvents statement on startup

Although this article applies only to the old Visual Studio 2008, I am writing it for completeness of the body of knowledge that I have built over the years about add-ins. And if you are a VSX developer who cares about your users/customers, chances are that your extension still supports Visual Studio 2005 / 2008 (which are widely used yet at companies because for some reason developers don’t always migrate to the latest version. See How many old Visual Studio versions does my add-in/package have to support?). Recently I encountered an issue in one of my scripts that remove add-in commands, and it took me a while to find that the root cause was a bug in Visual Studio 2008:

BUG: Visual Studio 2008 crashes if unloaded when an add-in executes DoEvents statement on startup

If you were in the VSX world in the VS 2008 era of add-ins, you may remember that there was another bug that caused VS 2008 to crash on startup:

BUG: Add-in causes Visual Studio 2008 crash when loaded

Fortunately both bugs were fixed in next releases.

MZ-Tools Articles Series: PRB: Window.Close doesn’t save changes if requested for .sql files in non-database projects

My new article is to document a bug that a customer of my MZ-Tools add-in reported some days ago, and that is caused by a bug (or problem) in the automation model (EnvDTE). It happens in the following scenario:

  • Using the latest versions of Visual Studio (it doesn’t happen with old versions such as VS 2005, 2008)
  • You add a .sql file to a project that doesn’t support .sql files, for example to a C# project. The problem doesn’t happen with projects that support .sql files such as database projects.
  • If you open the project item to get its (invisible) window, get its text document, modify it and close the window saving the changes, the changes are not persisted to disk.

You have the details and code to reproduce the problem here:

PRB: Window.Close doesn’t save changes if requested for .sql files in non-database projects
http://www.mztools.com/articles/2014/MZ2014027.aspx

I am not sure if this is a bug or not, because the project doesn’t support .sql files. There is an easy workaround, though. You can call:

window.Document.Save(“”);
window.Close(EnvDTE.vsSaveChanges.vsSaveChangesNo);

instead of:

window.Close(EnvDTE.vsSaveChanges.vsSaveChangesYes);

MZ-Tools Articles Series: HOWTO: Pass parameters programmatically to a command from a Visual Studio add-in

A question in the VSX forum has intrigued me enough to test a creative solution: to intercept a command execution to re-execute it with an input parameter that you can retrieve when the execution finishes. This can be useful in a scenario where a command can be executed asynchronously twice and you want to know which/when each execution is finished:

HOWTO: Pass parameters programmatically to a command from a Visual Studio add-in
http://www.mztools.com/articles/2014/MZ2014025.aspx

Visual Studio Extensibility (VSX) Forum FAQs about add-in development

There is a sticky VSX FAQ post in the Visual Studio Extensibility (VSX) Forum since more than one year ago that is intended to collect the FAQs about development of Visual Studio extensions (packages, add-ins, templates, isolated shell, etc.). Unfortunately there aren’t many FAQ entries in each category, which is a pity. Today I have added tons of them in the “Add-ins” category, my area of expertise, pointing to the most useful HOWTO articles of my MZTools Articles Series. Hopefully they are useful for people before posting in the forum:

VSX FAQ
http://social.msdn.microsoft.com/Forums/en-US/vsx/thread/0be62d3d-84b2-4e17-a306-bcc460621192

EnvDTE.Window.Kind vs EnvDTE.Window.ObjectKind

This afternoon I was writing an add-in for a new MZ-Tools series article and while I thought that EnvDTE.Window.Kind returned a Guid to identify the kind of a toolwindow, it actually returns the literal “Tool” for all toolwindows.

I revisited the article:

HOWTO: Getting information about Visual Studio windows from an add-in
http://www.mztools.com/articles/2009/MZ2009010.aspx

and I noticed that the information was incorrect and that in Visual Studio .NET 2003, 2005, 2008 and 2010 (I am unable to test Visual Studio .NET 2002 on Windows 7 64-bit), EnvDTE.Window.Kind doesn’t return a Guid but “Tool” for toolwindows and “Document” for document windows. It is the EnvDTE.Window.ObjectKind property which returns such Guid. So, I have updated the article to fix the misleading information.

MZ-Tools Resources about Visual Studio .NET extensibility updated for VS 2010

MSDN has a nice URL mechanism to reference several Visual Studio versions of the same documentation, for example:

Automation and Extensibility for Visual Studio (Visual Studio 2010)
http://msdn2.microsoft.com/en-us/library/xc52cke4(en-US,VS.100).aspx

Automation and Extensibility for Visual Studio (Visual Studio 2008)
http://msdn2.microsoft.com/en-us/library/xc52cke4(en-US,VS.90).aspx

Automation and Extensibility for Visual Studio (Visual Studio 2005)
http://msdn2.microsoft.com/en-us/library/xc52cke4(en-US,VS.80).aspx

Long overdue, but today I have updated the MZ-Tools Resources about Visual Studio .NET extensibility page with links to Visual Studio 2010 extensibility resources (downloads of SDKs, documentation, etc.).

More on devenv.exe /resetaddin not removing permanent commandbars

I think I forgot to blog about the resolution of this bug:

devenv.exe /resetaddin doesn’t fully reset the add-in
https://www.visualstudioextensibility.com/2009/06/23/devenv-exe-resetaddin-doesn-t-fully-reset-the-add-in

whose Microsoft Connect bug report is:

https://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=469322

The problem is, you see, that devenv.exe /resetaddin doesn’t remove permanent commandbars, only commands and buttons on commandbars. That means that if you are using permanent commandbars and not temporary ones, at the very least your uninstaller needs to take care of removing permanent commandbars explicitly because devenv.exe /resetaddin won’t do it. This can be done creating an instance of EnvDTE.DTE, locating the commandbar and calling EnvDTE.DTE.Commands.RemoveCommandBar (see HOWTO: Removing commands and UI elements during Visual Studio .NET add-in uninstallation). And not only the uninstaller: when debugging you may need to remove the commandbar too because VS 2005 and higher fire a new UISetup phase each time that you debug, so you get duplicated commandbars.

The temporary vs permanent approaches for commandbars is a nightmare for two reasons:

  • First, their own existence. A single approach would be much better. And the temporary one would be preferable. The reason for the permanent one is that for add-ins with a large number of commandbars and buttons, it takes less time to persist the UI on disk and retrieve it from there when launching VS than recreating the UI. I think that there aren’t many add-ins with lots of commandbars and buttons (certainly my MZ-Tools add-in is one with such large number of buttons, but I keep using the temporary approach). But if performance is a problem, then it is better to fix that rather than inventing a new approach. Some ideas for Microsoft to increase the performance of add-ins using the temporary approach are:

    • Provide a EnvDTE.Commands.Exist(commandName) method to test if a command exists or not (to create it only if it doesn’t exist). Currently you have to call the Item method which causes an (expensive) exception if the command doesn’t exist.
    • Provide a EnvDTE.AddInCommands collection that returns only the commands of add-ins, not the hundreds of commands of Visual Studio.
    • Make EnvDTE.Command.AddControl to behave as follows: if you are adding a button to a menu, set the CommandBarButton.Style to msoButtonIconAndCaption (VS already does this), but if you are adding it to a toolbar, set the CommandBarButton.Style to msoButtonIcon since it is more likely that style (without caption) on a toolbar. Currently VS defaults to msoButtonIconAndCaption also in this case, which means that after getting the CommandBarControl, you have to cast it to CommandBarButton and then change the Style property, which means that the button needs to be redrawn (a performance hit). I already reported this two years ago to no avail: Wrong default vsCommandStyle for CommandBarButtons created from add-ins. Even more, Visual Studio doesn’t work as supposed to do: Problems with ContextUIGUIDs and vsCommandDisabledFlagsValue in EnvDTE.Commands.AddNamedCommand (a bug yet to be acknowledged and fixed).
    • Simplify the way of getting transparent pictures for commands. The transparent color has been RGB=0,254,0 for long time which means that a color remapping must be performed. Hopefully this has been addressed in VS 2010 with support for 32-bit bitmaps with transparency in the alpha channel.
  • Second, the APIs are not consistent, which creates a lot of confusion. If both approaches need to exist, at least they would have to use the same methods with just one boolean parameter indicating if a commandbar is permanent or temporary. Currently you have:

    • CommandBars.Add to add temporary commandbars
    • CommandBar.Delete to remove temporary commandbars
    • Commands.AddCommandBar to add permanent commandbars (even if the CommandBars.Add method above has a Temporary parameter!)
    • Commands.RemoveCommandBar to remove permanent commandbars

Anyone can see that that mix of methods to add commandbars is bound to cause problems (why is there a AddCommandBar method in the Commands collection?) and certainly it is: the bug of devenv.exe /resetaddin can’t be fixed because the Commands.AddCommandBar method lacks a fundamental piece of information: the AddIn instance that is adding the commandbar. Without that information the IDE doesn’t know which add-in is the owner of a permanent commandbar and therefore can’t remove it.

Microsoft fixing bug “Standard user unable to load/unload COM-based add-ins registered for all users with the VS Add-in Manager on Windows Vista”

Two years after I reported it, it seems that MS finally understood that this was a bug and I have been notified today that it is no longer closed as “By design” but as “Fixed”:

Standard user unable to load/unload COM-based add-ins registered for all users with the VS 2008 Add-in Manager on Windows Vista
http://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=365846

This bug has plagued all of us developing add-ins with COM-registration (rather than .AddIn XML registration) for all users (not for current user) for backwards compatibility with VS.NET 2002 and/or 2003. Too bad that the fix comes so late that I doubt there will be a fix for VS 2008, only for VS 2010…but anyway, it will make VS 2010 a better product.