Happy New Year 2009 and MVP again!

Hello all, and Happy New Year! I have just received today the e-mail from Microsoft awarding me the Microsoft Most Valuable Professional (MVP) title again (this is the sixth one since 2004!). I am very grateful and excited about this award and along with feedback that I receive from people it really encourages me to keep devoting quite of my spare time to the community of developers extending Visual Studio, mainly with add-ins.

Some weeks ago I took some days off and I got inspired those days with four (yes, 4) new initiatives or projects that I would accomplish in 2009 to help developers of add-ins for Visual Studio, apart from writing a new bunch of MZ-Tools Articles Series and answering questions in the MSDN forum about Visual Studio Extensibility. I will announce them in the next weeks or months as they move from a “proof of concept” state to something deliverable.

The strange case of Visual Studio 2008 severely crashing loading an add-in

Some months ago a customer of my MZ-Tools add-in reported a crash in Visual Studio 2008 Team Suite when loading it. When an add-in crashes loading it, usually Visual Studio captures the exception or COM error and shows a semi-friendly messagebox indicating that the add-in has caused an exception or failed to load, and give you the chance of removing it. While sometimes the error is <Unknown Error> and you get only the error number (specially if the problem is found by the CLR loading the add-in and not executing the code), this crash was more severe: “Visual Studio needs to close”, and your only options are to close or to restart. MZ-Tools doesn’t have instrumentation yet, but after a couple of custom builds with traces sent to the customer I was able to determine that the problem happened creating the very first toolbar. Somehow the customer changed to Visual Studio 2008 Professional Edition and the problem disappeared so I closed the incident (falsely).

Last week it was a prospect who experienced the severe crash. It is not the best experience for a prospect to download a trial version of your product, install it and get such a crash. I knew that for such severe crashes the problem is not really my add-in but the prospect would think otherwise… Since the add-in is marked to load on startup, it crashes VS every time so chances are that he will uninstall and forget the product. But fortunately he reported it to me, so I troubleshooted it. After a couple of days verifying that the problem was actually MZ-Tools and not other extensions, that the referenced assemblies were present and that the versions were correct, I recalled this problem, that I had almost totally forgotten. I retreived the e-mails of the previous case, and the problem happened with VS 2008 Team Suite also this time. And when I was about to send him a minimal add-in that creates a toolbar to reproduce the problem, I searched the web and I found this post by Jamie Cansdale, former MVP colleague and author of TestDriven.NET (formerly NUnitAddIn):

VS 2008 crashes on startup when ‘Code Analysis Tools’ feature is not installed
http://weblogs.asp.net/nunitaddin/archive/2007/11/29/vs-2008-crashes-on-startup-when-code-analysis-tools-feature-is-not-installed.aspx

So, the problem happens in Visual Studio 2008 Team Suite if you don’t install the “Code Analysis Tools”. Since in the first case the user switched to Visual Studio 2008 Professional Edition, which doesn’t include the Code Analysis Tools (only Visual Studio 2008 Development Edition or Visual Studio 2008 Team Suite), the problem disappeared. In the second case, the prospect run the setup again and certainly the Code Analysis Tools were not installed. After installing them, MZ-Tools loaded fine.

Now, I have tried to reproduce the problem to report it to Microsoft to no avail:

My computer has Visual Studio 2008 Team Suite with the Code Analysis Tools and SP1. I have removed the Code Analysis Tools and the problem doesn’t appear. I have removed the SP1 and nothing. I have removed VS 2008 completely and I have installed it from scratch without the Code Analysis Tools and the problem doesn’t appear. So, I don’t know yet how to reproduce but at least I am glad that I know how to solve it and hopefully I won’t forget it again (I’ll force myself to check the “The strange case of …” series for those rare problems…)

I have also updated this article:

HOWTO: Troubleshooting Visual Studio and Office add-ins
http://www.mztools.com/articles/2007/MZ2007009.aspx

UPDATE (Dec 11, 2008): Finally I have reproduced the problem with a clean virtual machine and Visual Studio 2008 Development Edition without the “Code Analysis Tools” and without installing SP1. The problem happens when an add-in performs certain operations with commandbars of DTE such as:

  • Trying to create a toolbar
  • Trying to retrieve an nonexistent command bar
  • Trying to set the Name property of a Commandbar
  • Maybe others

The problem can be solved through two ways:

  • Installing the missing “Code Analysis Tools” component
  • Installing Service Pack 1

While not many users are affected by this bug since most of them perform a full installation of Visual Studio 2008 and/or install SP1, the problem is so nasty that you may want to detect this circumstance and show a warning when loading your add-in. Something like the following in the OnConnection method before manipulating CommandBars:

If IsVS2008TeamSuite() Or IsVS2008DevelopmentEdition() Then

   If Not IsCodeAnalysisToolsComponentInstalled() Then

      If Not IsVS2008SP1Installed() Then

         MessageBox.Show("This add-in is going to crash :-(")

      End If

   End If

End If

Some details to implement those functions:

  • You can detect if VS 2008 SP1 is installed using the registry key:

– HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\DevDiv\VSServicing\9.0\VSTS\<locale>, name “SP” for VS 2008 Team Suite

– HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\DevDiv\VSServicing\9.0\VSTD<locale>, name “SP” for VS 2008 Development Edition

Where <locale> is the language of Visual Studio, such as 1033 for English, 3082 for Spanish, etc. Your add-in can get the locale of IDE using the DTE.LocaleID property.

The SP value can be 0 (no SP installed) or 1 (SP1 installed).

  • You can detect if VS 2008 Team Suite installed if the registry key “HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\VisualStudio\9.0\Setup\VS\VSTS” exists.
  • You can detect if VS 2008 Development Edition installed if the registry key “HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\VisualStudio\9.0\Setup\VS\VSTD” exists.
  • You can detect if the “Code Analysis Tools” component is installed getting the folder of VS 2008 (reading the “ProductDir” name under the registry key above), appending “Team ToolsStatic Analysis ToolsFxCop” and checking if the file FxCopSdk.dll exists or not.

Notes:

  • VS 2008 without SP1 lacks the folder “Team ToolsStatic Analysis ToolsFxCop” if Code Analysis Tools are not installed (as expected).
  • VS 2008 SP1 creates that folder even if you don’t have Code Analysis Tools installed, but it doesn’t add DLLs, just some RepositoryCompatibility folder with some XML files.

The strange case of toolwindow not showing when the add-in is loaded on startup

Visual Studio preserves the visibility state of its own toolwindows (Solution Explorer, etc.) but not of toolwindows created by add-ins. It is up to the add-in to store the state of its toolwindows when unloaded, and restore them when it is loaded again. So, some add-ins can show their toolwindows when loaded and not only when the menu to show them is invoked. However, some developers are noticing that in some cases toolwindows don’t show when the add-in is loaded on startup, but they show if the add-in is loaded by hand using the Add-In Manager. If this is the case, chances are that it is because you are not using the OnConnection method correctly and the IDE is not fully initialized when the add-in is trying to show its toolwindow:

HOWTO: Use correctly the OnConnection method of a Visual Studio add-in
http://www.mztools.com/articles/2008/MZ2008004.aspx

This is just one of the many side effects of a badly designed IDTExtensibility2 interface that populates the MSDN forum with related questions every week…

The strange case of add-in setup not detecting running instances of Visual Studio 2008 on Windows Vista

If you are creating a setup for your Visual Studio add-in, chances are that you don’t want running instances of Visual Studio when the add-in is going to be installed or uninstalled. For my MZ-Tools add-in, I use the free InnoSetup, which is script-based and uses Pascal for custom code, and I wrote an article some time ago about how to create a setup for a Visual Studio add-in using InnoSetup.

A couple of weeks ago I noticed something strange: when running the setup on Windows Vista, it detected running instances of Visual Studio .NET 2002, 2003 and 2005, but not of Visual Studio 2008. Actually, I detected the problem on Windows 2008 Server with the Visual Studio 2010 CTP, but I was able to reproduce the problem with Windows Vista and Visual Studio 2008.

The setup detects running instances of Visual Studio by using the GetActiveOleObject function for the ProgID of each Visual Studio version (“VisualStudio.DTE.7”, etc.):

function IsVSRunningByProgID(ProgID: String):Boolean;
var
IDE: Variant;
begin

try
IDE := GetActiveOleObject(ProgID);
except
end;

if VarIsEmpty(IDE) then
Result := False
else
Result := True
end;

The GetActiveOleObject function returns a running (if any) COM (ActiveX) server given a ProgId. Somehow it was failing for Visual Studio 2008 whose ProgId is “VisualStudio.DTE.9.0”. I tried to reproduce the problem with a VB6 program using the GetObject function, and it worked, but I soon realized that the GetObject function of VB6 always return an instance: if none is running, it creates one.

Incidentally, the setup worked as expected on Windows XP so I suspected that the User Account Control (UAC) of Windows Vista (and Windows Server 2008) could be the culprit. And the final detail was that while Visual Studio .NET 2002, 2003 and 2005 require by default admin rights (so you get a “consent prompt” from the UAC of Windows Vista), Visual Studio 2008 was designed to run without admin rights, so it launches without “consent prompts” on Windows Vista, running as a standard user even if you are an administrator. Searching on the InnoSetup forums, I confirmed that on Windows Vista a process running with elevated priviledges (such as my setup) cannot interact with a COM process running with low priviledges (such as Visual Studio 2008), so the GetActiveOleObject call fails (“Operation unavailable”) and no instance is returned, as if no instance was executing. In fact, the setup worked as expected if I run Visual Studio 2008 as an administrator (using the context menu) and getting the “consent prompt” of the UAC.

So, which is the solution for this problem? The forums mentioned something about mutexes or something that I am not willing to investigate, because sometimes when you devote a lot of time to a tough problem you realize that you don’t have a problem actually, or that it is not so severe. For example, an add-in can be installed perfectly even with Visual Studio running, it just needs to copy some files and add some registry entries. Its toolbar and menus won’t appear in the running instances of Visual Studio but if the user goes to the Add-In Manager, it will be there. There is only a problem when uninstalling the add-in, because removing the commands (and permanent UI if used) requires to persist the changes and if there is a running instance of Visual Studio the changes will be overwritten when this other instance is closed. But I guess I’ll have to live with that.

For applications that are not setups, such as applications automating the IDE (or for setups that allow you to execute .NET code), you can use System.Diagnostics.Process.GetProcessByName(“devenv”) and it will work.

The strange case of 8013141A loading a Visual Studio add-in

A developer posted a couple of days ago in the MSDN forum about Visual Studio Extensibility that loading his add-in caused and exception with error number <Unknown Error> (8013141A). Of course, searching with Google doesn’t always offer much information about these bizarre errors, nor the tools of the Windows SDK for which this error is, well, unknown too.

Since the section of my article about troubleshooting crashes in add-ins didn’t help much, I have enhanced it with further and more detailed explanations, and a mention to this error:

HOWTO: Troubleshooting Visual Studio and Office add-ins
http://www.mztools.com/articles/2007/MZ2007009.aspx

More on Visual Studio and .NET version numbering

Numbering is quite easy for any normal person (or even child) that you ask: 1, 2, 3, 4… For programmers it begins to get weird since many of them would say 0, 1, 2, 3… and when programmers need to version things, it goes absolutely crazy. It should be easy, though: a major number, a minor number (both quite visible to the end user) and some internal build number no so visible. So, you would have version 1.0. And the next major version would be 2.0. And some minor incremental version like 2.1. And something in between like 2.5. However early in the modern era of computing for the masses (that is, MS-DOS and Windows) we got something like Windows 3.11 for Workgroups (rather than 3.2) or Windows NT 3.51 (rather than Windows NT 3.6). And even in same cases letters like Windows NT 4.0 SP 6a. And we got four parts for versioning from Microsoft (major, minor, build, revision) and programmers from Oracle used even five parts. And then marketing people introduced a new scheme using years so you had Windows 95, Windows 98, and then something like Windows 98 SE, and then to something completely different without the year like Windows ME (Millenium Edition, don’t worry if you missed it) and then back to the year with Windows 2000 and then forward again without years like Windows XP or Vista and then back to square 1 (or 0?) with plain numbers again like Windows 7 (but not 7.0). OK, I am also guilty and I created MZ-Tools 4.0, then MZ-Tools 2005 and then back to MZ-Tools 6.0. I promise the next one will be 7.0 🙂

Now, to Visual Studio and .NET versioning. I wrote some time ago about some inconsistencies in the numbering used to version. I have created a more complete table. It would be nice that the table would be something like:

Visual Studio Commercial version 2002 2003 2005 2008 2010 (CTP)
Visual Studio ProgId VisualStudio.DTE.7.0 VisualStudio.DTE.7.1 VisualStudio.DTE.8.0 VisualStudio.DTE.9.0 VisualStudio.DTE.10.0
Visual Studio installation folder Microsoft Visual Studio 7.0 Microsoft Visual Studio 7.1 Microsoft Visual Studio 8.0 Microsoft Visual Studio 9.0 Microsoft Visual Studio 10.0
Visual Studio solution format 7.0 7.1 8.0 9.0 10.0
Visual Studio registry key 7.0 7.1 8.0 9.0 10.0
DTE version 7.0 7.1 8.0 9.0 10.0
.NET Framework folder v1.0 v1.1 v2.0 v3.0, v3.5 v4.0
SDK folder C:\Program Files\Microsoft Visual Studio 7.0\SDKv1.0 C:\Program Files\Microsoft Visual Studio 7.1\SDKv1.1 C:\Program Files\Microsoft Visual Studio 8.0\SDKv2.0 C:\Program Files\Microsoft Visual Studio 10.0\SDKv4.0
SDK registry key name (under HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft.NET\Framework) sdkInstallRootv1.0 sdkInstallRootv1.1 sdkInstallRootv2.0 sdkInstallRootv4.0

But actually it is like this:

Visual Studio Commercial version 2002 2003 2005 2008 2010 (CTP)
Visual Studio ProgId VisualStudio.DTE.7 VisualStudio.DTE.7.1 VisualStudio.DTE.8.0 VisualStudio.DTE.9.0 VisualStudio.DTE.10.0
Visual Studio installation folder Microsoft Visual Studio .NET 2002 Microsoft Visual Studio .NET 2003 Microsoft Visual Studio 8 Microsoft Visual Studio 9.0 Microsoft Visual Studio 10.0
Visual Studio solution format 7.00 8.00 9.00 10.00 11.00
Visual Studio registry key 7.0 7.1 8.0 9.0 10.0
DTE version 7.00 7.10 8.0 9.0 10.0
.NET Framework folder v1.0.3705 v1.1.4322 v2.0.50727 v3.0, v3.5 v4.0.11001
SDK folder C:\Program Files\Microsoft Visual Studio .NET 2002\Framework\SDK C:\Program Files\Microsoft Visual Studio .NET 2003\SDKv1.1 C:\Program Files\Microsoft Visual Studio 8\SDKv2.0 C:\Windows\Microsoft.NET\Framework\v4.0.11001\sdk (*)
SDK registry key name (under HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft.NET\Framework) sdkInstallRoot sdkInstallRootv1.1 sdkInstallRootv2.0 sdkInstallRootv4.0

(*) Notice that it uses the Microsoft .NET root folder and not the Visual Studio root folder.

It is left to the reader as an exercise to print this post, mark with a circle the differences between both tables and post a comment with your differences count 🙂

And why is this so important? For most users of Visual Studio, it really doesn’t matter. But for people developing extensions (add-ins, packages, etc.) for Visual Studio, it matters, because the extension needs to integrate within the Visual Studio host. It needs to place files in some folders (1). It needs to add/remove some entries to the registry (2). In needs to automate DTE for some tasks (3). It needs to get the paht to devenv.exe for others (4). It needs to get tools from the SDK to register (5). Its setup needs to use the Visual Studio ProgId registry key (6). Etc, etc.

(1) To register XML-based add-ins

(2) To register COM-based add-ins

(3) To remove add-in commands in VS.NET 2002/2003

(4) To remove add-in commands in VS 2005 and higher with devenv.exe /ResetAddIn

(5) To register COM-based add-ins with regasm.exe /codebase using a 3rd party installer such as InnoSetup.

(6) To detect if Visual Studio is installed or it is running.

And when your extension needs to target lots of Visual Studio versions for many years, you really need a table like the one above, because your brain won’t be able to recall all and if you did the proposed exercise you know by now that versioning patterns are unpredictable in Visual Studio and .NET (except for the “Visual Studio registry key” row, until now).

How to ask questions in a forum to increase your chances of an answer

Being developers I guess we all get the same feeling when some user of our application tell us that the app “doesn’t work”, or “it gives me an error” without further details. I am always tempted to reply “it works for me” to the first case and “which are the ‘first name’ and ‘last name’ of the error?” for the second case, to see if they get that more information is needed to do something about it. Yet after years in the forums I keep seeing lame posts written by developers that fail to give a meaningful subject, the version of the product that are using, the error that are experiencing, the code to reproduce it (or they provide the whole file of code with tons of lines), etc. I wonder how they expect to get a prompt and useful answer…

So today I decided to do something about it and I have written a sticky post in the MSDN forum about Visual Studio Extensibility:

How to ask questions to increase your chances of an answer
http://social.msdn.microsoft.com/Forums/en-US/vsx/thread/9307ca0b-d152-4c31-85f5-05b6166d7410

How many old Visual Studio versions does my add-in/package have to support?

I’m sure this is a question that every developer of extensions for Visual Studio, whether add-ins or packages, wonders from time to time. If you develop extensions for in-house use, you can drive, incentivate or even force your organization to migrate to the latest version of Visual Studio. But if you develop extensions commercially, things are quite different.

At the time of this writing we have the following Visual Studio versions:

  • Visual Studio .NET 2002, released in February 2002.
  • Visual Studio .NET 2003, released in April 2003.
  • Visual Studio 2005, released in October 2005.
  • Visual Studio 2008, released in November 2007.
  • Visual Studio 2010, to be released at the end of 2009 or in 2010.

Five releases start to be a lot of releases… even if you have managed to have a single code base for your extension (with some conditional compilation), or maybe even the same binary for several Visual Studio versions (with some dynamic adaptation to the Visual Studio version hosting the extension), and maybe the same setup, nothing can avoid you a lot of testing, to ensure that your extension works correctly on each Visual Studio version, because from time to time Microsoft introduces unintentionally new bugs. Furthermore, you would like to use new features of the .NET Framework like Generics of .NET 2.0, which you can’t use if your codebase is still to be build against .NET 1.0 or 1.1. You are also tired of having four whole releases of Visual Studio installed on your machine with identical shortcuts in the quick launch toolbar of your Windows (sort of Visual Studio 2008, which introduced the version number “9” in the icon). And some of the Visual Studio releases are not supported on your Windows Vista but since you want the latest OS, you don’t want to go back to Windows XP, so you install them anyway, and they work for the most part, but some very used features like Find hangs and you get frustrated…

So, you really wonder if you could drop support for VS.NET 2002. If your extension is a package, VS.NET 2002 didn’t provide support for 3rd party packages so there is no question. If your extension is an add-in, then you could probably drop support because VS.NET 2002 was the version 1.0 of the new IDE and it was somewhat incomplete and lacking some features that Microsoft took only one year to replace it instead of the usual two years cycle. And by the time people learned .NET and decided whether to use it for some serious project or not, VS.NET 2003 was out.

What about VS.NET 2003? This version introduced the Visual Studio Industry Program (VSIP) for packages, which in VS 2005 would evolve into the Visual Studio SDK. So, you really would like to get rid of VSIP and use only the new VS SDK, and dropping support for this version would mean that you can move your codebase to .NET 2.0, and your add-in can get rid of COM using toolwindows without a shim control, using XML-based registration rather than Registry-based registration, managed satellite DLLs instead of native C++ satellite DLLs, etc. And you wonder, how many people is still using VS.NET 2003? Hey, that’s stuff of five years ago! Could I get some usage statistics from somewhere, Microsoft perhaps? Do I send an e-mail to my customers? Do I drop support anyway?

Well, if you are a successful commercial vendor, you already know that all is about the customer, not about you, your technology, your preferences or your desires (if you are still a geek with disdain for marketing and sales there is good stuff to learn out there). So, let’s talk about the customer:

  • Customers hate when they have some software and hardware that at some point is not supported by the vendor, no matter how old. I remember that I had an HP CD recorder that when Microsoft shipped Windows XP was no longer supported. I found an article from Microsoft pointing to the HP web site, and indeed HP stated that they wouldn’t provide Windows XP drivers for that model. My CD recorder could be old and slow (4x, I think) but at that time it worked for my needs and if I needed to buy a new one to work with Windows XP, I may well purchase it from another vendor…. I haven’t purchased an HP product since then for that reason.
  • While you as a developer may have a MSDN subscription to get all the Microsoft software for development, many customers don’t. They buy some Visual Studio version and don’t upgrade unless they have the money and some compelling reason to do it (and maybe WPF, AJAX, etc, don’t qualify as a compelling reason). Think that the MSDN subscription is per-developer, not for a whole team. So only medium or big companies with special agreements (“Enterprise”, “Open”, “Select”) with Microsoft get new software as it is released. Students and hobbyists also get the latest versions in the form of Express editions, but these don’t support extensions, and you wouldn’t get much money from them anyway.
  • Even if a company has a software subscription with Microsoft and receives the new Visual Studio versions, they may have dozens or maybe more than a hundred .NET projects. And they have better (business) things to do than to migrate them just for technology purposes, forced by a vendor. Their company has already installed some .NET Framework version, and their projects and the Visual Studio version that they are using meet their needs. Or they use the latest Visual Studio version for new projects, but they don’t migrate the old ones because it takes time to do it.

So, despite your big desires of getting rid of old Visual Studio versions, as a developer of add-ons you need to support many previous versions of Visual Studio, and for many years. It’s the price you have to pay for developing extensions and not standalone applications. If I had doubts about dropping VS.NET 2003 support for my MZ-Tools add-in, the last two support e-mails that I have received about my MZ-Tools 6.0 for VS.NET add-in were from people still using VS.NET 2003… and you would be really surprised of how many people still download the version of my MZ-Tools 3.0 version of my add-in for Visual Basic 5.0 each month despite I would think that everybody had migrated to Visual Basic 6.0…

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

VS SDK, packages, add-ins, macros and more…