Category Archives: MZ-Tools Articles Series

MZ-Tools Articles Series: INFO: Testing a Visual Studio add-in against new Visual Studio tools or extensions from Microsoft

When you create your Visual Studio extension, whether an add-in or package, likely you test it most of the time against project types provided by Visual Studio out of the box, such as VB.NET/C# projects, smartdevice projects, database projects, etc.

Long time ago I wrote an article warning that likely add-ins fail throwing exceptions when tested against 3rd party project types, because they tend to be “unmodeled projects” (meaning that they don’t support automation):

PRB: Add-ins fail with 3rd party project kinds in Visual Studio .NET
http://www.mztools.com/articles/2004/MZ2004006.aspx

New project types can introduce new icons for project/project items, new text file types that are searchable, etc. so your add-in can be affected.

While you may argue that it is annoying and time-consuming to test an add-in/package against every single new project type that any 3rd party company feels the need to create, there are new project types from a company that you should test: the new project types from Microsoft itself. This is because they are extensions for Microsoft products and technologies and very likely they will be installed on tons of computers with Visual Studio. My latest article mentions some of the new extensions or tools for Visual Studio that you should test against:

INFO: Testing a Visual Studio add-in against new Visual Studio tools or extensions from Microsoft
http://www.mztools.com/Articles/2009/MZ2009003.aspx

MZ-Tools Articles Series: HOWTO: Prevent dead CommandBarButtons when Visual Studio or an add-in crashes

This is another problem that was bugging me for quite some time: if an add-in uses a temporary user-interface rather than a permanent one when adding buttons to a built-in toolbar of Visual Studio, the add-in must remove the buttons when unloaded, typically keeping a reference to the CommandBarButton instance and calling the CommandBarButton.Delete method in the OnDisconnection method.

This approach has a problem that was affecting some customers of my MZ-Tools add-in: if Visual Studio or the add-in crashes, the add-in doesn’t have the chance of removing those buttons and they stay there forever, creating duplicates the next one that the add-in is loaded.

A better approach is to delete the command, rather than the button, when the add-in is unloaded (the command should be recreated rather than deleted to keep keyboard bindings). Deleting a command deletes all buttons, even “dead” ones. While this new approach doesn’t prevent duplicated buttons, they only stay there for a session. Using this new approach also solves the sporadic problem of COMException 0x800A01A8 that I already blogged about.

I have just written a new MZ-Tools Series article about this:

HOWTO: Prevent dead CommandBarButtons when Visual Studio or an add-in crashes
http://www.mztools.com/articles/2009/MZ2009002.aspx

FWIW, MZ-Tools 6.0.0.93 (February 1, 2009) uses this new approach, which solves both problems.

Announcing the revised MZ-Tools Articles Series with C# samples and more

One of the initiatives that I want to accomplish this year 2009 is to revise and update all the more than 125 articles that I have written all these years since 2004 in the MZ-Tools Articles Series to include the following:

  • Samples in C#.  I have provided all the samples in the articles in VB.NET since it is my preferred development language and I assumed that every C# developer could understand the code. But I have noticed that:
    • To write add-ins in C# is somewhat more difficult due to the lack of optional parameters in C# (version 4.0 will support them, BTW) and other things.
    • Not every C# developer reading the articles bothers to try the VB.NET code to run the sample and then translates it to C#. Instead, they keep inventing code that it is not in the sample.

    So I have decided to make it easy for everybody and provide the samples of add-ins in VB.NET and C#. Macros will remain in VB.NET since C# is not supported as a macro language.

  • Revision of the Visual Studio version(s) that the articles apply to. Many articles were written when VS 2005 and VS 2008 were not released yet. So I am revising if each article still applies to new versions, such as if a bug has been fixed, etc.
  • “Copy” button to copy the code sample to the clipboard. Currently it works only with Internet Explorer. For FireFox it is more complicated and I haven’t found yet a satisfactory solution using the FireFox interfaces or the Flash approach. Security is a major concern in all browsers and operating systems such as Windows Vista and getting access to the clipboard of the client machine is increasingly more difficult. Nonetheless, FireFox is my preferred browser, so I will keep trying in the future.
  • Revision of the nomenclature prefixes used in the sample code. I am now trying to use the Microsoft guidelines, avoiding prefixed for types.
  • Revision of the “Related Articles” section and the end of each article. Some articles will reference now other articles that were not written yet when they were written.
  • Hopefully less spelling and grammar mistakes :-). I am from Spain so I don’t speak English natively, and the editor that I use lacks a spell checker.

I have created a spreadsheet with all the articles that need modification and this happens to be a huge task that will take me months keeping a pace of one article per workable day, but I think it will be worth. This also means that this year will be less new content, but I have still some topics to write about.

Here you have a sample of a revised article:

HOWTO: Add a popup command bar to the context menu of a code window of Visual Studio .NET

MZ-Tools Articles Series (update) HOWTO: Automating Visual Studio .NET from outside the IDE

I am these days trying to create a single .NET application that can automate all the Visual Studio versions installed on a machine (from Visual Studio .NET 2002 to Visual Studio 2010). For that purpose I have created a .NET application using Visual Studio .NET 2002 so it uses .NET Framework 1.0, which can run on any .NET Framework. Since I want to use early binding, I need to add a reference to EnvDTE.dll. And here I have found a problem; it happens that there are two versions of EnvDTE.Dll:

  • Version 7.0.3300.0: it is installed by Visual Studio .NET 2002 and 2003, but not by Visual Studio 2005 or higher.
  • Version 8.0.0.0: it is installed by Visual Studio 2005 or higher, but not by Visual Studio .NET 2002 or 2003.

So, depending on the Visual Studio versions installed, you can have one version, the other, or both.

If the ,NET application references version 8.0.0.0, it won’t work when only Visual Studio .NET 2002 or 2003 are installed. If it references version 7.0.3300.0, it won’t work when only Visual Studio 2005 or higher is installed. Using a .config file to redirect version 7.0.3300.0 to 8.0.0.0 won’t help, because if the system has only version 7.0.3300.0 installed, after the redirection it won’t find version 8.0.0.0.

That means that you can’t automate all Visual Studio versions starting with Visual Studio .NET 2002 or 2003 using early binding. You have to use late binding, either using Option Strict Off (VB.NET) or Reflection (VB.NET / C#).

I have updated accordingly the article that I wrote back in 2005:

HOWTO: Automating Visual Studio .NET from outside the IDE
http://www.mztools.com/articles/2005/MZ2005005.aspx

MZ-Tools Articles Series: BUG: Standard user unable to load/unload COM-based add-ins registered for all users with the VS 2008 Add-in Manager on Windows Vista

Almost a couple years ago I wrote an article The Add-In Manager of Visual Studio 2005 got broken…and won’t be fixed for SP1 and while Visual Studio 2008 fixed that problem, it has introduced a new one when running on Windows Vista, and guess what, VS 2008 SP1 doesn’t fix it either, so I guess we will have it until the next version of Visual Studio… Again, the problem happens with COM-based add-ins, not with add-ins using a .AddIn XML file. I guess that most developers of commercial add-ins still need to support Visual Studio .NET 2003 (my MZ-Tools add-in even supports Visual Studio .NET 2002) and they may want to use a single code base for the code and the setup, so they still use COM registration for add-ins for Visual Studio 2005/2008 (at least this is my case), so it would be good to get this bug fixed.

Here is the article explaining the bug:

BUG: 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://www.mztools.com/articles/2008/MZ2008025.aspx

And here you have the bug report on the Microsoft Connect web site to vote for it:

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

MZ-Tools Articles Series: HOWTO: Using the Process Monitor (ProcMon) tool to diagnose Visual Studio add-ins problems

Last year I wrote a quite popular article HOWTO: Troubleshooting Visual Studio and Office add-ins, to diagnose many common problems with add-ins for Visual Studio or even Office. One invaluable tool to diagnose a whole range of problems with an add-in setup or the Add-In Manager of Visual Studio is the Process Monitor (ProcMon) tool, formerly developed by SysInternals and now part of Microsoft Technet. My MZ-Tools add-ins for Visual Studio (all versions), VB6, VB5 and VBA are installed and registered smoothly for tons of users every week, but from time to time I get a support incident about the setup failing due to something wrong on the user machine and I diagnose the problem requesting the user to run the tool and sending the trace back to me. While the Process Monitor tool applies to any developer, not just add-in developers, not everybody is familiar with it, so I wrote this article to explain how to use the tool and to refer my users to it. As an example, I will show why Visual Studio 2008 fails to recognize .addin files when stored in the folder “%ALLUSERSDOCUMENTS%\Microsoft\MSEnvShared\AddIns” that was introduced by Visual Studio 2008.

HOWTO: Using the Process Monitor (ProcMon) tool to diagnose Visual Studio add-ins problems
http://www.mztools.com/articles/2008/MZ2008024.aspx

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

I have updated the article that I wrote back in January about default folders to place .AddIn registration files for add-ins to include actual examples for Windows Vista since the original article only showed Windows XP examples. I have also provided better information about how to get the actual folder names correctly.

Overall the naming of Windows Vista folders is perfect because:

  1. It doesn’t localize folder names
  2. It uses meaningful names such as:
    • “C:\Users\<username>\AppData\Roaming” while Windows XP used “C:\Documents and Settings\<username>\Application Data” (how do you remember that it is roaming?)
    • “C:\Users\<username>\AppData\Local” while Windows XP used “C:\Documents and Settings\<username>\Local Settings\Application Data”

but because of backwards compatibility with Windows XP it uses junction points and all this folders stuff is really a mess. Anyway, the updated article:

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

MZ-Tools Articles Series: HOWTO: Add an error with navigation to the Error List from a Visual Studio add-in

It is conspicuous that the EnvDTE80.ErrorItems collection introduced by VS 2005 lacks an Add method to add errors to the ErrorList, so it was a common belief, apparently even within Microsoft and also mine until recently that only SDK packages can add errors to the ErrorList. There is good news: there is not only one approach, but two!

The first one was explained by Dave Sexton in this forum post and it uses the OutputWindowPane.OutputTaskItemString method but has some limitations.

I was investigating another approach and it was not until today that I became aware of the difference between GetService (that didn’t work in my sample) and GetGlobalService 🙂

Of course there is always in the VS automation world something else that doesn’t work as expected such as a +1 line number offset that others have posted in the MSDN forum more than once, but I managed to work around it.

So, here is the second working approach:

HOWTO: Add an error with navigation to the Error List from a Visual Studio add-in
http://www.mztools.com/articles/2008/MZ2008022.aspx

I always get the feeling that the automation model (EnvDTE) should be much more powerful and intuitive (no ErrorItems.Add method but OutputWindowPane.OutputTaskItemString to add errors to the Error List???) than what it is, and that the bridge between the automation model and the SDK is much more complicated that it should be (EnvDTE.DTE lacking a GetService method, assemblies that are only in the GAC or that you need to get installing the SDK that I don’t want to install, IVSHierarchy <-> EnvDTE.Project conversions, 0-based collections vs 1-based collections, etc.). The result is several hours spent making something simple work…

MZ-Tools Articles Series: HOWTO: Get an OutputWindowPane to output some string from a Visual Studio add-in or macro

To deal with international versions of Visual Studio and other Microsoft products (such as Office) has always been tricky. I think to remember that many years ago some version of Excel went as far as localizing the VBA statements (or macro language before VBA, not sure now), so while in English you had:

For i = 1 to 100
...
Next

in Spanish you had:

Para i = 1 a 100
...
Siguiente

I suppose that was intended to get accountants into macros without forcing them to learn two languages: VBA and, hmmm, English. Of course the experiment didn’t work well and currently VBA is English-only.

Today things should be easy if two rules are followed:

  • The user interface is localized, but the names of objects in the internals (ie: programming) should not be localized. So, classes should have a property such as “Caption” that is localized (in .NET the Caption property has been replaced by the Text property but it’s the same) and a property such as “Name” that should NOT be localized. Every programmer can understand the difference between “Name” and “Caption”, right?
  • When locating an item in a collection, the English name should be used as index, never the localized name.

Alas, the reality is not so easy:

  • The Office Commandbar class has the Name and NameLocal properties (and lacks a Caption property). You can learn searching the MSDN help (don’t expect the Intellisense help to tell the difference) that NameLocal actually means something like LocalizedName. The difference between “Name” and “NameLocal” is not so clear as between “Name” and “Caption”.
  • Visual Studio command names are also localized (http://msdn.microsoft.com/en-us/library/aa290377(VS.71).aspx), supposedly because a programmer can type them in the Command window, I guess. But MS did it right and the Commands collection can be queried by English names even on localized Visual Studio versions
  • Visual Studio output window panes (EnvDTE.OutputWindowPane) have a Name property, and guess what? The Name is localized, so in Spanish is “Generar” instead of “Build”. I know, I know, VS is so extensible that it uses Guids to identify things (as if fully qualified names were not enough) and therefore the EnvDTE.OutputWindowPane class has a Guid property too that you should use to locate a specific output window pane. My point is that the Name property of an EnvDTE.OutputWindowPane should be “Caption” and it would not cause havoc when an English developer receives a call from a German customer saying that the product doesn’t work with German Visual Studio because the developer thought that Name would not be localized. The last thing that I want to see is forcing developers to hardcode strings in their product with all the localized names that the product needs with its Korean, Chinese, Japanese, etc. strings…). Even the code generated by the add-in wizard of Visual Studio does the same as I explained in another article.
  • With all that precedents, since you cannot be sure that your product will work with international Visual Studio versions, you have to test, but VS forces you to install the whole product in another language, rather than supplying downloadable localized resource DLLs to put in some folder (in VS.NET 2002/2003 you could get them from the CD of the international versions but in VS 2005 they are hidden in CAB files…)

So, my latest article explains how to get an output window pane by Guid without learning Chinese 😉

HOWTO: Get an OutputWindowPane to output some string from a Visual Studio add-in or macro
http://www.mztools.com/articles/2008/MZ2008023.aspx

MZ-Tools Articles Series: HOWTO: Retrieve the Command that created a CommandBarControl from a Visual Studio add-in or macro

The question “How do I retrieve a Command from a CommandBarControl?” has been posted in the forums at least a couple of times and my answer always was “It’s not possible” because the CommandBarControl lacks a Command property, which is the intuitive thing that one would think. It was not until today that I realized that MS provided a way, although far from intuitive:

HOWTO: Retrieve the Command that created a CommandBarControl from a Visual Studio add-in or macro
http://www.mztools.com/articles/2008/MZ2008021.aspx