Assuming that:
- The C# source code below is compiled under .NET 2.0 (CLR 2.0); and
- The above application uses the
app.config
listed below; and
- Only .NET 4.0 (CLR 4.0) is installed on the environment of the client executing the application,
then which version of .NET is internally loaded to execute the application on the client's environment?
Description
The console application below will simply show that its CLR version is v4.0.30319
in the console, but @Reed Copsey's answer of the stack (CLR 2.0 vs 4.0 performance?) shows that .NET 2.0 is loaded in this case. Moreover, at MSDN it says when useLegacyV2RuntimeActivationPolicy
is set to false false
:
Use the default activation policy for the .NET Framework 4 and later,
which is to allow legacy runtime activation techniques to load CLR
version 1.1 or 2.0 into the process.
It sounds like .NET 2.0 is loaded in spite of the app.config
having a .NET 4.0 configuration. Have I misunderstood anything?
Source
C# source code
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
string version = Environment.Version.ToString();
Console.WriteLine(version);
}
}
}
app.config
<?xml version="1.0"?>
<configuration>
<startup useLegacyV2RuntimeActivationPolicy="false">
<supportedRuntime version="v4.0.30319"/>
</startup>
</configuration>
The bottom line is that under your scenario, you specified .Net 4 as your only supported runtime, so your app will load with CLR 4.
The CLR behavior with your program is exactly as designed:
When I run your test app with the supportedRuntime
as v4.0, Process Explorer shows it loads mscorlib v4.0.30319.
When I run with supportedRuntime
as v2.0.50727, Process Explorer shows it loads mscorlilb v2.0.50727.
When I run with no supportedRuntime
element, Process Explorer shows it loads mscorlilb v2.0.50727.
This blurb from Microsoft states that the supportedRuntime
element defines the specific version on which your program runs:
By default, an application runs on the version of the .NET Framework that it was built for. If that version is not present and the application configuration file does not define supported versions, a .NET Framework initialization error may occur. In this case, the attempt to run the application will fail.
To define the specific versions on which your application runs, add one or more elements to your application's configuration file. Each element lists a supported version of the runtime, with the first specifying the most preferred version and the last specifying the least preferred version.
There are two separate elements at play, here. Only the supportedRuntime
element applies to your scenario.
The supportedRuntime
element defines the CLR versions on which your app will run, in the preferred order. If you list supported runtimes, then those CLR versions will be used, going down the list from top to bottom until an installed CLR version is found. If you don't list support runtimes, then your program will run with the version of the CLR against which it was compiled.
The useLegacyV2RuntimeActivationPolicy
element applies only to mixed-mode assemblies --- programs or DLLs that contain managed (.Net) and unmanaged (native) code. Your sample program isn't a mixed-mode assembly. For mixed-mode assemblies, setting the value to false
(the default), or not setting it all, uses the new .Net 4 in-process side-by-side loading for mixed-mode assemblies, so your app can run with CLR 4, and load a mixed-mode assembly in the same process using CLR 1.0-2.0. Setting it to true
essentially reverts to the previous functionality prior to .Net 4, where the in-process side-by-side functionality is disabled, and whatever CLR version is selected to run the app will attempt to load your mixed-mode assembly. The CLR version used to load the mixed-mode assembly will be whichever one is selected to run the app, based on which version was used to compile the app, and your listed supported runtimes, if any.
There's an MSDN Magazine article and an MSDN article about .Net 4 loading and In-Process Side-by-Side (In-Proc SxS) execution for COM components, which also has an impact on your scenario without COM components. Prior to .Net 4, if you compiled your app with a version of the CLR, and that version wasn't available on the system at runtime, the app would automatically run on a newer version of the CLR if it was installed. As of .Net 4, apps now won't run with a newer version of the CLR unless you specify the newer version in the supportedRuntimes
element.
Here's a quote from the MSDN article:
Application developers. Side-by-side hosting has almost no effect on application developers. By default, applications always run against the version of the .NET Framework they were built on; this has not changed. However, developers can override this behavior and direct the application to run under a newer version of the .NET Framework (see scenario 2).
Library developers and consumers. Side-by-side hosting does not solve the compatibility problems that library developers face. A library that is directly loaded by an application -- either through a direct reference or through an Assembly.Load call -- continues to use the runtime of the AppDomain it is loaded into. You should test your libraries against all versions of the .NET Framework that you want to support. If an application is compiled using the .NET Framework 4 runtime but includes a library that was built using an earlier runtime, that library will use the .NET Framework 4 runtime as well. However, if you have an application that was built using an earlier runtime and a library that was built using the .NET Framework 4, you must force your application to also use the .NET Framework 4 (see scenario 3).
Finally, if you're on Vista, Win7, Server 2008, Server 2008 R2, you automatically have CLR 2.0 installed. Therefore, if you were to remove your supportedRuntimes
element, or change it to v2.0.50727, you might still have CLR 2.0 available as a runtime.