.NET Frameworks, CLRs and Visual Studio add-ins

Each time that a new Visual Studio version appears on the horizon I guess that every add-in developer wonders about the question of how to make his add-in to support that new version: can I use the same current binary DLL that I have (with some tweaks)? Do I need a separate binary? The question of how to target several IDEs with the same binary (and setup) would be a great subject for a MZ-Tools Series Articles (maybe in the next months) but for now suffice to say that if your add-in is intended for VB.NET/C# a single binary can target VS.NET 2002/2003 and a different binary can target VS 2005/2008 (a single binary can’t target all because VS 2005 introduced a new DLL for commandbars). First, some clarifications about .NET Framework and Common Language Runtimes (CLRs):
  • A CLR is the base of a .NET Framework: it is composed by the loader/binder, JIT/NGEN, garbage collector, security model, profiling and debugging APIs, etc. and the Base Class Libraries.
  • A .NET Framework is a CLR plus additional libraries: Windows Forms, WPF, WF, WCF, etc.

We have two kinds of .NET Frameworks:
  • Side-by-side model: the .NET Framework is installed independently of other .NET Frameworks (it coexists with them). It uses its own CLR and it is complete. This is the case of .NET Framework 1.0 (VS.NET 2002), .NET Framework 1.1 (VS.NET 2003) and .NET Framework 2.0 (VS 2005).
  • Layer cake model: the .NET Framework is installed on top of other .NET Framework. It uses an existing CLR (not providing a new one) and it just supplies additional libraries. This is the case of the .NET Framework 3.0 (which introduced WPF, WF and WCF, but used CLR 2.0) and the .NET Framework 3.5 (VS 2008, it uses CLR 2.0 too). Notice that there is no CLR 3.0 or CLR 3.5.

Only VS 2008 can target several .NET Frameworks (2.0, 3.0 or 3.5). Previous VS versions can only target the .NET Framework they introduced.

An assembly compiled against a .NET Framework can run on ulterior .NET Frameworks (and CLRs) without problems (at least in theory, more on this later). For example, a .NET 1.0 assembly can run on a .NET 1.1 Framework. The opposite is not true for two reasons:
  • An assembly compiled against a given CLR can not run on a previous CLR. For example, an assembly compiled against CLR 2.0 can not run on CLR 1.0 or 1.1 (they know nothing about generics, for example).
  • An assembly compiled against a .NET Framework can not run on a previous .NET Framework, even if it shares the same CLR, because of missing libraries. For example, an assembly compiled against the .NET Framework 3.5 using WPF cannot run on the .NET Framework 2.0 despite both use the CLR 2.0 because a machine with only the .NET Framework 2.0 would lack the WPF libraries.

Ok, enough theory. Let’s start with some questions:
  • If I compile a standalone application (not an add-in) against CLR 1.1 and the machine has both CLR 1.1 and CLR 2.0, which CLR uses? Answer: by default it uses CLR 1.1, although it can be configured through a .config file to run on the lastest installed .NET Framework.
  • If I compile an add-in against CLR 1.0 and I register and run it under VS.NET 2003, which CLR uses, 1.0 or 1.1? Answer: it uses 1.1 (!), as you can verify putting a message box with the System.Environment.Version.ToString() in the OnConnection method. Add-ins, which run hosted inside some application, must all run with the same CLR (the lastest supported by the host). So, you can create an add-in with VS.NET 2002 (CLR 1.0) and run it on both VS.NET 2002 and VS.NET 2003. But you can’t create it in VS.NET 2003 (CLR 1.1) and run it on VS.NET 2002. Similarly, you can create an add-in with VS 2005 (CLR 2.0) and run it on VS 2008. And you could even create it on VS 2008 with .NET Framework 2.0 and use it on VS 2005 because both use CLR 2.0!

More questions about VS 2010, which is on the horizon (there is a CTP available):
  • Which .NET Framework does it use? Answer: it uses a new .NET Framework 4.0.
  • Does the .NET Framework 4.0 follow a side-by-side model or a layer cake model? Answer: it follows a side-by-side model.
  • Being a side-by-side .NET Framework, which CLR does it use? Answer: it introduces a new CLR 4.0.
  • Shouldn’t it be CLR 3.0 (after CLR 1.0, 1.1 and 2.0)? Answer: Microsoft tries to match the .NET Framework version and the CLR version, so CLR 3.0 is skipped.
  • Does it mean that .NET Framework 2.0/3.0/3.5 is no longer installed with VS 2010? Answer: it happens that VS 2008 introduced multi .NET Framework targetting, and VS 2010 follows suit targetting .NET Framework 2.0, 3.0, 3.5 and 4.0, so all of them are installed. Update (December 4, 2009): the installation of VS 2010 RTM will not include .NET Framework 2.0, 3.0 or 3.5, only .NET Framework 4.0. While VS 2010 can target those .NET Frameworks, you will have to download and install them.
  • So, can my binary add-in compiled against CRL 2.0 run on VS 2010 if registered properly?: Answer: yes (at least with the current CTP)

Now this gets tricky: the CLR 4.0 can coexist in the same Windows process with a previous CLR (2.0), something that was not possible before!. In the previous example, an add-in compiled against CRL 1.0 runs on CLR 1.1 (not on CLR 1.0) when loaded in VS.NET 2003. The same applies to other hosts such as Outlook, which uses the latest .NET Framework installed for all add-ins. But this can cause problems. For example, Microsoft discovered a nasty bug in a .NET 1.0 Outlook add-in used by their executives that when they installed .NET 1.1 caused a crash due to some new .NET 1.1 optimizations when starting threads. For that (and other reasons), a host can now use several CLRs (4.0 and 2.0) at the same time, loading each add-in in the CLR it was created for. This may or may not be a desirable thing, so you can configure it with a config file. (I am not sure which is the default behavior). This leads to the most interesting question:
  • So, my binary add-in compiled against CLR 2.0, does it run under CLR 4.0 or CLR 2.0 when loaded in VS 2010? Answer: well, in my tests with the current CTP, it runs under CLR 4.0 (the same behavior of previous VS versions). I am not sure if this is the default behavior, if it is something that will change later or what. I personally prefer this behavior (running under 4.0) because in my MZ-Tools add-in there are features that have to load assemblies from the .NET Framework to get property names of controls, etc. If the add-in runs under CLR 2.0 (because it was compiled against it), I doubt it could handle assemblies of CLR 4.0…

Very interesting (and tricky) stuff, isn’t it? You can learn more about the new CLR 4.0 in this PDC 2008 session:

Microsoft .NET Framework: CLR Futures
http://channel9.msdn.com/pdc2008/PC49/