何时以及为何需要 supportedRuntime 元素和 sku 属性?

When and why do I need the supportedRuntime element and sku attribute?

在 Visual Studio 中创建的大多数(如果不是全部)C#(以及 F# 和 VB)库和可执行项目中,有一个自动添加的 app.config 文件指定 运行时间版本和目标框架名称 (TFM):

<configuration>
  <startup>
    <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.0" />
. . .

即使完全没有 app.config 文件,编译器似乎总是生成一个程序集级属性,如 ILDASM 所示:

.custom instance void [mscorlib]System.Runtime.Versioning.TargetFrameworkAttribute::.ctor(string) = ( 01    // ....NETFramework
                                                                                                      ..    // ,Version=v4.6.1.
                                                                                      bytes snipped-> ..    // .T..FrameworkDis
                                                                                                      ..    // playName..NET Fr
                                                                                                      61  ) // amework 4.6.1

.csproj 文件确实指定了目标框架,我猜这就是目标在构建过程中从哪里传递到编译器的地方。

如果配置文件中没有 <startup> 部分,可执行文件似乎 运行 就好了。 The documentation 解释了 什么 属性是什么意思,但是,看了很多年,我一直不明白 为什么 在配置中需要它们文件。然而,我主要处理 Windows 的桌面应用程序。

明确指出“使编译为目标 .NET 4.0 的程序在更高版本上表现得像 运行s 是不可能的”,如果相反,我会感到非常惊讶, 运行在较低版本的框架上安装程序也是可能的。

那么,应用开发者在什么情况下需要在应用的.config文件中指定运行时间的版本和TFM,是否要一直重复信息被编译器硬编码到二进制文件中?乍一看,这个要求似乎违反直觉。


更新 2018-06-29:X-ref:我要求对 GitHub 问题 dotnet/docs#6234.

中的文档进行澄清

targetFramework 属性主要确定用于编译目的的 .NET Framework。它还用于确定引用 .NET 库 (DLL) 的兼容性。但是,当您将 .NET 项目作为应用程序分发并将其部署在其他计算机上时,就会出现问题。问题是"what happens if the target computer does not have the .NET Framework version installed used during compilation?"。这就是 supportedRuntime 元素具有一定意义的地方。 supportedRuntime 元素列表中的第一个版本匹配将用于 运行 应用程序。如果 supportedRuntime 元素中的 none 版本与目标计算机上安装的版本相匹配,那么最新版本的框架将用于 运行 应用

我希望这个解释能回答你的问题。

需要声明您的应用程序实际兼容的框架版本。假设,我们有一个面向 .NET Framework 4.7.2 的应用程序,并尝试在仅安装了 .NET Framework 4.5 的机器上 运行 它。如果我们添加这个 app.config

<?xml version="1.0" encoding="utf-8"?>
<configuration>
<startup><supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.7.2"/></startup></configuration>

Windows 将显示一条很好的错误消息,要求安装所需的框架版本:

如果我们省略 app.config,Windows 将尝试 运行 它,然后应用程序将在第一次遇到特定于 .NET Framework 4.7.2 且不存在的功能时崩溃在已安装的框架版本中。

请注意,文档中所说的“此元素应由所有使用 .NET Framework 1.1 或更高版本构建的应用程序使用”的说法具有误导性。它可能被解释为“This element is required to application to 运行 on .NET 1.1+”,而实际上它只意味着 .NET 1.1 改变了以前的语法在 .NET 1.0 requiredRuntime 语法中使用。更多时候 supportedRuntime 并不是申请 运行 所必需的,它只是为了美观。

一个常见的情况是 supportedRuntime 确实 需要应用到 运行 是当我们有面向 .NET 的应用程序时 2.x-3.x 并尝试在只有 4.x 的机器上 运行 它(例如,Windows 10 有 4.6+ 但没有 .NET 2.x-3.x 默认安装)。在这种情况下,如果 app.config 中没有 supportedRuntime,应用程序将根本不会 运行,即使 4.x 大部分与以前的版本兼容。添加 <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.0" /> 将解决问题。


因此,总而言之,它不会复制程序集元数据中的信息,而是提供 Windows 额外信息,说明如何将应用程序与其兼容的框架版本连接起来,以及向用户询问什么版本如果目标计算机上不存在,请安装。