Application runtime compatibility - Visual studio.NET 2003, 2005 & .NET Framework 1.1, 2.0

With the release of .Net 2.0 and VS.NET 2005 there are lot of questions on compatibility and co-existence between the different runtimes and applications that utilize them. The following pointers may be helpful in understanding those.( Terminology - VS -> Visual Studio, .NET FW -> .NET Framework)

           
1. Multiple versions of .NET and Visual Studio.NET *can* peacefully co-exist in a machine as long as they were installed in the chronological order (7.0, 7.1 and 8). Importantly, a solution created in a older version of VS.NET will open up with that version only when you double click the solution file( File->Open doesn’t do this – the solution will be opened in the current VS if possible). Be warned, .NET framework versions and VS.NET are hardbound to each other. The following pairs are hardbound to each other
a. VS.NET 2003 & .NET FW 1.1
b. VS.NET 2005 & .NET FW 2.0
This means using VS.NET 2003 you can target only .NET FW 1.1 framework applications only. Also, VS.NET 2005 cannot target the .NET FW 1.1 framework. (Why so? https://blogs.msdn.com/johnri/archive/2005/11/29/498219.aspx will tell you...)

2. However applications can be ‘run’ under a .NET FW runtime different from the one they were compiled with. For ex, an application written using VS.NET 2003 can be ‘run’ under the 2.0 runtime. VS.Net 2005 applications cannot run under the pre – 2.0 runtime but they should be theoretically able to run under all the future versions of .NET runtime unless the application uses some stuff thats part of the breaking changes. This can be achieved using the config file approach explained in the next point.(Read more about compatibility and breaking changes at https://www.gotdotnet.com/team/changeinfo/default.aspx). To get the official word from MSDN use https://msdn.microsoft.com/netframework/default.aspx?pull=/library/en-us/dnnetdep/html/netfxcompat.asp. This can be achieved using the config file approach explained in the next point.

3. The .NET framework runtime is actually a set of dlls – this means there can only be one set of these dlls in a process. No matter what we do, we CANNOT have more than one runtime versions of .NET in a process. And, the first one to be loaded wins. If your process loads .NET V 1.0 first and if you attempt to load 1.1 or 2.0 subsequently they will all fail.

4. An unmanaged application can also use the .NET framework runtime by means of in-process runtime interaction with a managed component. By default all unmanaged applications load the latest available versions of the .NET runtime installed in the machine. This behavior can be changed by using a ‘config file’ and effecting the change.

a. Consider a machine that has both .NET FW 2.0 and 1.1 installed. Consider an unmanaged app um.exe that interacts with managed com components. By default, the um.exe will try to run under the 2.0 runtime only. If the managed component it loads comes from the 1.1 world, the app will have weird unexpected behaviors. It can throw up some error messages in the form of exceptions or some unexpected crash or a totally unfriendly error message. This will get in the way of debugging such an application using Visual Studio as well. To ensure this app always uses .NET 1.1 a config file called um.exe.config( in the same folder as um.exe )should be created and that file will have the following contents
<?xml version ="1.0"?>
<configuration>
<startup>
<supportedRuntime version="v1.1.4322" />
</startup>
</configuration>

The MSDN link that talks about this - https://msdn2.microsoft.com/en-us/library/9w519wzk.aspx

b. The CorBindToRuntimeEx - https://msdn2.microsoft.com/en-us/library/99sz37yh.aspx can be used to ‘hard bind’ an unmanaged application to a .NET framework runtime. This function does much more that enabling this. Read the API reference before you decide to use this approach.

c. When compiling your unmanaged application set the /clr flag using the properties dialog. This will make your application as ‘managed’ and will always load the runtime that came with the VS.NET you are compiling this app in. This technique is ‘c’ – only if you don’t want a & b.

5. Assembly redirection – It is possible to have one reference to a .NET Framework version 1.1 assembly and another reference to a .NET Framework version 2.0 assembly, you would use the pattern shown in the following pseudocode

<assemblyBinding xmlns="..." appliesTo="v1.1.4322">
<! — .NET Framework version 1.1 redirects here. -->
</assemblyBinding>

<assemblyBinding xmlns="...">
<!-- Redirects meant for all versions of the .NET Framework. -->
</assemblyBinding>

Having these entries in the machine.config file will let you use the redirected assembly whenever the original assembly is specified. However, this doesn’t mean that you are using 2 different runtimes. This technique will work after a runtime has been loaded. So this is *not* a way to load a different runtime.
For more information on assembly redirection - https://msdn2.microsoft.com/en-us/library/433ysdt1.aspx

Do let me know if you have any questions.

Note : Thanks to Ravi Uppaluru, Manoj Mohunthan & Jaganathan Thangavelu for pointing out missing and vague items(duly corrected ;-) ) in the intial draft of this article.

[Edit history]
1. Feb 27, 2006 - added John Rivard's blogs entry explaining VS-.NET FW pairing. Thanks to Dat Bui for pointing this out.

2. Aug 18, 2006 - Some of the issues mentioned here are taken care by https://blogs.msdn.com/seshadripv/archive/2006/06/09/623871.aspx