Force Microsoft Build Tools 2015 to include mscorl

2020-06-21 05:39发布

问题:

I have written an application in Visual Studio 2015 that uses C# 6.0 features and targets .NET 4.5.2. When I build it using Microsoft Build Tools 2015, which is what is done by our TeamCity server, the resulting bin folder also contains a copy of mscorlib.dll. The problem here is that the mscorlib.dll being copied is the .NET 4.6 DLL, which causes problems at runtime.

I have replaced my call to string.Format() with the new string interpolation syntax to work around the problem. That, however, shoves the underlying problem under the carpet instead of addressing it: Why is the .NET 4.6 DLL included in my build and how can I force the 4.5.2 DLL to be included in its place?

If you are interested in the runtime problem this caused for me, it caused my:

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

To be interpreted as (link -- which only exists in .NET 4.6):

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

Instead of (link):

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

回答1:

When you build your solution on a TeamCity build agent, TeamCity uses a version of MSBuild that you had installed on the agent. Each version of MSBuild is created to build DLLs that target a specific version of .NET. For example, I think that MSBuild 2015 targets .NET 4.6.

In order to use MSBuild 2015 to build DLLs that target .NET 4.5.2, you need to also install what is called a .NET 4.5.2 targeting pack (also referred to as development pack in some places):

  • https://www.microsoft.com/net/download/visual-studio-sdks
  • What's the difference between the .NET Framework SDK and the Targeting pack

If you do not install the targeting pack and try to build against an older version of .NET with the wrong build tools, as was my case, then MSBuild 2015 tries to compensate by building the only way it knows how: By following the rules of .NET 4.6 (which should be backwards-compatible to 4.5.2 anyway) and throwing in a .NET DLL (mscorlib.dll) in the build folder.

In most cases, this would have still worked fine, except my code made use of String.Format() which suffered a very subtle breaking change between 4.5.2 and 4.6.