如何在 .NET Framework 4.6.1 下强制编译为以 .NET Framework 4 为目标的应用程序到 运行?

How do I force an application compiled to target .NET Framework 4 to run under .NET framework 4.6.1?

我做了相当多的研究,但没有找到任何合适的答案。这是场景。

我有一个针对 .NET Framework 4 编译的应用程序。在运行时,我希望该应用程序在 .NET Framework 4.6.1 中实际执行。到目前为止我找到了两个选项。

  1. 在 .NET Framework 4.6.1 下重新编译应用程序
  2. 将 configuration/startup/supportedRuntime 元素添加到 app.config 版本="v4.0" sku=".NETFramework,Version=v4.6.1"

选项 1 不可取,因为它需要重新发布软件。

选项 2 不符合我的预期。它似乎检查是否安装了 CLR 4.0(不是框架 4.0),如果没有提示下载适当的 SKU 来安装它。安装后,应用程序仍然在.NET Framework 4.0

下运行

作为测试,也是发布此问题的原因,我创建了一个小型控制台应用程序来简单地执行此操作

Console.WriteLine(System.Net.ServicePointManager.SecurityProtocol);

如果是针对 .NET Framework 4 编译的,则输出为

Ssl3, Tls

如果是针对 .NET Framework 4.6.1 编译的,则输出为

Tls, Tls11, Tls12

具体的 ServicePointManager.SecurityProtocol 确定与 4 vs 4.6.1 框架的一般问题完全无关,恐怕没有明确的答案,因为它在一般情况下不相关(所有情况都是可能是具体的,如果你愿意的话)。

具体的答案,这里是这样描述的:Mitigation: TLS Protocols

Starting with the .NET Framework 4.6, the System.Net.ServicePointManager and System.Net.Security.SslStream classes are allowed to use one of the following three protocols: Tls1.0, Tls1.1, or Tls 1.2. The SSL3.0 protocol and RC4 cipher are not supported.

如果安装了 4.6+,那么你确实可以改变程序的行为 w/o 重新编译它,如文章中所述,只需将这一行添加到你的 .config 文件中:

<configuration>
  ...
  <runtime>
    ...
    <AppContextSwitchOverrides value="Switch.System.Net.DontEnableSchUseStrongCrypto=false" />
  </runtime>
  ...
</configuration>

I am ... asking about the general case of forcing an application compiled against framework 4.0 to run using framework 4.6.1

好吧,您已经完成了 app.config 文件条目。它赋予了this feature,用户必须先安装4.6.1才能获得程序运行。他所要做的就是单击“是”按钮。这并不是说经常使用,当用户负责使用 Windows Update 更新他的机器时,4.6.1 应该始终出现在机器上。如果他故意不那么 "forcing" 不太可能受到欢迎。

但这实际上不是你的问题。您希望您的程序 表现得 就像它安装在 4.6.1 上一样。这是一个 非常 不同的鱼缸。请注意 2) 不起作用,您不能轻易欺骗运行时。编译器在您的可执行文件中嵌入了一个 TargetFrameworkAttribute attribute 那是 运行时用来确定其行为方式的文件。 have a look-see with ildasm.exe,双击清单就可以看到了。您的 app.config 条目不会覆盖它。

最大的问题是 .NET 4.5 与 显着 在运行时和框架程序集中的破坏性变化有根本的不同。重到足以保证将版本升级到 5.0。但这总是会给客户带来很多痛苦和痛苦,如果运行针对 4.0 的程序,Microsoft 会使用书中的所有技巧来使 4.5(及更高版本)表现得像 4.0。

不只是一招。一种核心方法是将参考程序集存储在 c:\Program Files (x86)\Reference Assemblies 目录中。它们存储 目标包 文件。当您最初构建程序时,您使用了存储在 C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework.NETFramework\v4.0 中的那些。如果您重新定位您的项目,那么您将使用存储在 v4.6.1 中的项目。他们非常不同。值得注意的是 SecurityProtocolType enum you are talking about is different, it acquired two new values. This is a breaking change, a .NET 4.0 program is liable to suffer a heart-attack when it sees SecurityProtocolType.Tls12, it has no idea whatsoever what it could mean. Building a program with the wrong targeting pack files can cause deeply mystifying exceptions.

和其他技巧。 post .NET 4.0 版本中的错误修复根据 [TargetFrameworkAttribute] 有选择地启用,错误的向后兼容性对于确保程序不会观察到已更改的运行时行为很重要。 CLR 中充满了 appcompat 开关。我可以指向 CoreCLR 中的源代码文件,但它太可怕了,无法查看:)

所以不,让编译为目标 .NET 4.0 的程序表现得像在更高版本上运行一样是不可能的。您了解的注册表项和应用程序上下文开关 高度 仅特定于 ServicePointManager.SecurityProtocol 属性。他们在那里只是因为您不是唯一想要这样做的客户,TLS 版本相当重要。只需确保新的枚举值不会使您的程序出错。