【问题标题】:When executing an application on .net 4.0, compiled under .net 2.0在 .net 4.0 上执行应用程序时,在 .net 2.0 下编译
【发布时间】:2011-08-03 05:20:02
【问题描述】:

假设:

  1. 下面的C#源代码是在.NET 2.0(CLR 2.0)下编译的;和
  2. 上述应用程序使用下面列出的app.config;和
  3. 在执行应用程序的客户端环境中只安装了 .NET 4.0 (CLR 4.0),

那么内部加载了哪个版本的 .NET 以在客户端环境中执行应用程序?

说明

下面的控制台应用程序将在控制台中简单地显示其 CLR 版本为 v4.0.30319,但 @Reed Copsey 对堆栈的回答 (CLR 2.0 vs 4.0 performance?) 表明在这种情况下加载了 .NET 2.0。此外,MSDN 表示当 useLegacyV2RuntimeActivationPolicy 设置为 false false

使用 .NET Framework 4 及更高版本的默认激活策略, 允许旧的运行​​时激活技术加载 CLR 版本 1.1 或 2.0 进入进程。

尽管app.config 具有 .NET 4.0 配置,但听起来好像已加载 .NET 2.0。我有什么误解吗?

来源

C# 源代码

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>

【问题讨论】:

    标签: c# .net .net-4.0 .net-2.0 version


    【解决方案1】:

    底线是,在您的场景下,您指定 .Net 4 作为您唯一支持的运行时,因此您的应用将使用 CLR 4 加载。

    您的程序的 CLR 行为与设计完全一致:

    当我使用 supportedRuntime 作为 v4.0 运行您的测试应用程序时,Process Explorer 显示它加载了 mscorlib v4.0.30319。

    当我使用 supportedRuntime 作为 v2.0.50727 运行时,Process Explorer 显示它加载 mscorlilb v2.0.50727。

    当我在没有 supportedRuntime 元素的情况下运行时,Process Explorer 显示它加载了 mscorlilb v2.0.50727。

    This blurb from Microsoft 声明supportedRuntime 元素定义了程序运行的特定版本:

    默认情况下,应用程序在为其构建的 .NET Framework 版本上运行。如果该版本不存在并且应用程序配置文件未定义支持的版本,则可能会发生 .NET Framework 初始化错误。在这种情况下,运行应用程序的尝试将失败。

    要定义运行应用程序的特定版本,请将一个或多个元素添加到应用程序的配置文件中。每个元素都列出了一个支持的运行时版本,第一个指定最喜欢的版本,最后一个指定最不喜欢的版本。


    这里有两个独立的元素在起作用。只有supportedRuntime 元素适用于您的方案。

    supportedRuntime 元素以首选顺序定义了您的应用将在其上运行的 CLR 版本。如果您列出支持的运行时,那么将使用这些 CLR 版本,从上到下从列表向下直到找到已安装的 CLR 版本。如果您没有列出支持的运行时,那么您的程序将使用编译它所针对的 CLR 版本运行。

    useLegacyV2RuntimeActivationPolicy 元素仅适用于混合模式程序集 --- 包含托管 (.Net) 和非托管(本机)代码的程序或 DLL。您的示例程序不是混合模式程序集。对于混合模式程序集,将值设置为 false(默认值)或不全部设置,使用新的 .Net 4 进程内并行加载混合模式程序集,因此您的应用程序可以运行使用 CLR 4,并使用 CLR 1.0-2.0 在同一进程中加载​​混合模式程序集。将其设置为true 本质上会恢复到 .Net 4 之前的先前功能,其中进程内并行功能被禁用,并且选择任何 CLR 版本来运行应用程序都将尝试加载您的混合模式部件。用于加载混合模式程序集的 CLR 版本将是选择用于运行应用程序的版本,具体取决于用于编译应用程序的版本以及列出的支持的运行时(如果有)。


    有一个MSDN Magazine article 和一个MSDN article 是关于 COM 组件的 .Net 4 加载和进程内并行 (In-Proc SxS) 执行,这也会对没有 COM 组件的场景产生影响。在 .Net 4 之前,如果您使用某个版本的 CLR 编译您的应用程序,并且该版本在运行时在系统上不可用,则如果安装了该应用程序,该应用程序将自动在较新版本的 CLR 上运行。从 .Net 4 开始,除非您在 supportedRuntimes 元素中指定较新版本,否则应用程序现在将无法使用较新版本的 CLR 运行。

    这是 MSDN 文章的引述:

    应用程序开发人员。 并行托管对应用程序开发人员几乎没有影响。默认情况下,应用程序始终针对构建它们的 .NET Framework 版本运行;这没有改变。但是,开发人员可以覆盖此行为并指示应用程序在较新版本的 .NET Framework 下运行(参见方案 2)。

    库开发者和消费者。 并行托管并不能解决库开发者面临的兼容性问题。由应用程序直接加载的库(通过直接引用或通过 Assembly.Load 调用)继续使用它加载到的 AppDomain 的运行时。您应该针对您想要支持的所有版本的 .NET Framework 测试您的库。如果应用程序是使用 .NET Framework 4 运行时编译的,但包含使用早期运行时构建的库,则该库也将使用 .NET Framework 4 运行时。但是,如果您有一个使用早期运行时构建的应用程序和一个使用 .NET Framework 4 构建的库,则必须强制您的应用程序也使用 .NET Framework 4(请参见方案 3)。

    最后,如果您使用的是 Vista、Win7、Server 2008、Server 2008 R2,you automatically have CLR 2.0 installed。因此,如果您要删除 supportedRuntimes 元素,或将其更改为 v2.0.50727,您可能仍然可以将 CLR 2.0 用作运行时。

    【讨论】:

    • 因此,useLegacyV2RuntimeActivationPolicy 元素不会影响确定加载哪个 .net 版本,我的问题中提到的@Reed Copsey 的回答似乎不正确。
    • @jwJung - 正确,useLegacyV2RuntimeActivationPolicy 不适用于像您的示例这样的纯 .Net 应用程序。如果您有一个带有 COM 组件的应用程序,useLegacyV2RuntimeActivationPolicy 将仅适用于用于加载 COM 组件的 .Net CLR 版本。您的 .Net 应用程序仍将使用为 supportedRuntimes 标记定义的规则。我不明白 Reed Copsey 的回答怎么可能是正确的。
    • 没有理由等待更好的答案。感谢您的努力和回答。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-04-05
    • 2011-05-20
    • 1970-01-01
    相关资源
    最近更新 更多