强制 Microsoft Build Tools 2015 为框架的目标版本而不是 4.6 包含 mscorlib

Force Microsoft Build Tools 2015 to include mscorlib for the targeted version of the framework instead of 4.6

我在 Visual Studio 2015 年编写了一个应用程序,它使用 C# 6.0 功能并面向 .NET 4.5.2。当我使用 Microsoft Build Tools 2015 构建它时,这是由我们的 TeamCity 服务器完成的,生成的 bin 文件夹还包含 mscorlib.dll 的副本。这里的问题是被复制的mscorlib.dll是.NET 4.6 DLL,这会导致运行时出现问题。

我已将对 string.Format() 的调用替换为新的字符串插值语法以解决该问题。然而,这将根本问题隐藏起来而不是解决它:为什么 .NET 4.6 DLL 包含在我的构建中,我如何强制将 4.5.2 DLL 包含在它的位置?

如果您对这对我造成的运行时问题感兴趣,它会导致我的:

string.Format(CultureInfo.InvariantCulture, "{0}='{1}'", "key", "value")

解释为 (link -- 仅存在于 .NET 4.6 中):

System.String System.String.Format(System.IFormatProvider, System.String, System.Object, System.Object)

而不是(link):

System.String System.String.Format(System.IFormatProvider, System.String, params System.Object[])

当您在 TeamCity 构建代理上构建解决方案时,TeamCity 会使用您在该代理上安装的 MSBuild 版本。创建每个版本的 MSBuild 都是为了构建针对特定 .NET 版本的 DLL。例如,我认为 MSBuild 2015 的目标是 .NET 4.6。

为了使用 MSBuild 2015 构建面向 .NET 4.5.2 的 DLL,您还需要安装所谓的 .NET 4.5.2 目标包(在某些地方也称为开发包):

如果您没有安装目标包并尝试使用错误的构建工具针对旧版本的 .NET 进行构建(就像我的情况一样),那么 MSBuild 2015 会尝试通过构建它知道的唯一方式来进行补偿:通过遵循 .NET 4.6 的规则(无论如何它应该向后兼容 4.5.2)并在构建文件夹中放入一个 .NET DLL(mscorlib.dll)。

在大多数情况下,这仍然可以正常工作,除了我的代码使用了 String.Format(),它在 4.5.2 和 4.6 之间发生了非常微妙的破坏性变化。