Distinguishing .NET Versions

.NET versions can be 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 v4) versioning of .NET assemblies.

Versioning Made Confusing

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
1.1 (?)
2.0 2.0
4.0 4.0.?.? 4.0

As can be seen from the table there are currently three 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-v3.5 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.  v4 is a new runtime so if an application needs v2 support then a previous framework must be installed as well.

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, 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

With the release of v3.5 some new assemblies were added.  Again, since the runtime did not change (still 2) the core assemblies remain 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  The new assemblies added for v3.5 (LINQ, for example) get an assembly version of

(NOTE: v4 will be released in 2010 so it will be come the new standard going forward.  Visual Studio 2010 will ship with only the v4 framework.  VS2010 will support previous versions but you must install them manually.  VS 2010 does support loading projects from previous versions.  If you load a legacy project and the appropriate framework is not installed then you will get a dialog prompting you to: download the missing version, ignore the project or retarget to the newer version.  Unfortunately retargeting is the only real option.  VS will not recognize any framework not available when it loaded.  Therefore if you try to load a legacy solution then you will get this dialog for each project unless the legacy framework is installed.  Be sure to install v3.5 before trying to convert a VS 2008 project under VS 2010.)

Determining the Version

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.  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. 

To determine the runtime (CLR) version use Environment.Version.

Side-by-side Versioning

Prior to v4 the application determined the CLR version to use.  If you built a v3.5 app then you used the v2 runtime.  This can cause all sorts of problems – take two examples.  In example one an assembly written for v1 is loaded.  The assembly was built and tested against v1.1 and might not be compatible with the newer v2 framework.  In example two we have a v1.1 app that attempts to load a v2 assembly.  In this case the assembly might not have all the features it expected and will generate an error.  Neither of these are good scenarios.

Starting with v4 a single application can actually be running multiple versions of the framework at the same time.  The goal was to allow each assembly to run against the version it was built against.  Can this cause issues?  Most definitely but time will tell if it was worth the effort involved.  A full discussion of side-by-side runtime versioning is beyond the scope of this article.  Refer to the following link for more information: http://msdn.microsoft.com/en-us/magazine/ee819091.aspx