Practical Programming Pearls For .NET Developers

Distinguishing .NET Versions

Created: 16 January 2008

With the advent of .NET v3.5 it is starting to get confusing when you are trying to determine what version of the framework a program uses.  Gone are the days of all binaries carrying the same version number.  This article will attempt to explain the current (as of v3.5) versioning of .NET assemblies.

First it is necessary to clarify that there are actually two different version numbers in .NET: framework and runtime.  The runtime version determines what version of the CLR a program uses.  The framework version determines what version of the framework is being used.  In this article framework versions will be preceded by a v (as in v1.0 or v2.0) whereas the runtime version will be listed as simply a number.

The following table identifies the different runtime and framework versions.

Framework Version Assembly Version Runtime Version
1.0 1.0.0.0 1.0
1.1 1.1.0.0 (?)
2.0 2.0.0.0 2.0
3.0 3.0.0.0
3.5 3.5.0.0

As can be seen from the table there are currently only two versions of the runtime while there are quite a few versions of the framework. The above table ignores the updates to the versions due to service packs.  Implicit in the table is the fact that if you install any version of the framework from v2 on you will get the v2 runtime.  Therefore it is not necessary to install v2 and then v3.0 and then v3.5.  Just install v3.5 if you want v2.0 support.

As evident from the table the current runtime version is 2 and it has been in use for several framework versions.  You can confirm this by looking at some of the core system assemblies such as Mscorlib, System or System.Windows.Forms.  Each of these assemblies shipped with .NET originally or were added in v2.0 and therefore contain a version number of 2.0.0.0, in Visual Studio.

When v3.0 came out it made a few changes to the core assemblies (a service pack, if you will) and added a few new assemblies (WPF and WCF).  Since the runtime did not change the runtime version remains 2.  However since the new WPF and WCF assemblies were added in v3.0 they received an assembly version of 3.0.0.0.

With the release of v3.5 some new assemblies were added.  Again, since the runtime did not change (still 2) the core assemblies remain 2.0.0.0 even though they were updated (a service pack that was also released for v2.0).  The WPF and WCF assemblies from v3.0 were also updated but remain 3.0.0.0.  The new assemblies added for v3.5 (LINQ, for example) get an assembly version of 3.5.0.0.

As a result if you are writing a v3.5 WPF application you are actually using the same version of WPF as a v3.0 application running on the same machine and the same version of the core framework as a v2.0 application.  In theory a machine with v3.5 has the same runtime as a machine with only v2.0 and the latest service packs installed.  Reality rarely follows theory.  However it is true that on the same machine all v2.0+ applications use the same runtime assemblies.

Confused yet?  A general guideline you can use is to look at the version of the assembly.  It is an indication of either which framework the assembly was introduced in or the runtime version that it was built for.  Programmatically you can use Environment.Version to get the runtime version of an application.  For a specific assembly you can use Assembly.ImageRuntimeVersion to get the runtime version the assembly was built for.  In most cases it will be the same version as the application being run but, due to versioning policies, the assembly's runtime version might be lower than the application's runtime version.  It can never be higher.

At this time there is no real way to determine the framework version an application was built against.  The framework version is predominantly for determining which assemblies to reference anyway and what features to enable so it does not really have any runtime significants anyway.  If you truly must know then you can use hueristics to find the highest assembly version for the system assemblies.  Once you have that you'll have the (minimal) framework version.  As an aside note that the runtime enforces only the runtime version number of an assembly.  If you were to try to load a v2 application on a machine without v2 installed you'll get an error saying the runtime version is invalid.  However if you try to load a v3.5 application on a machine with only v3.0 it might or might not work depending upon whether you actually use any v3.5 features and reference any v3.5-only assemblies.