I have a Jenkins build server set up on Windows Server 2016. I have 'Build Tools for Visual Studio 2017' (latest version of MSBuild) installed. When I try to build a project targeting .Net 4.0 I get this error message:
C:\Program Files (x86)\Microsoft Visual Studio\2017\BuildTools\MSBuild\15.0\Bin\Microsoft.Common.CurrentVersion.targets(1122,5): error MSB3644: The reference assemblies for framework ".NETFramework,Version=v4.0" were not found. To resolve this, install the SDK or Targeting Pack for this framework version or retarget your application to a version of the framework for which you have the SDK or Targeting Pack installed. Note that assemblies will be resolved from the Global Assembly Cache (GAC) and will be used in place of reference assemblies. Therefore your assembly may not be correctly targeted for the framework you intend.
So I check 'C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework.NETFramework\v4.0' and find that, sure enough, there are no dlls in this folder, just xml files.
So I try to install the full .Net 4.0 framework thinking that will install the reference assemblies but I get these messages:
1) Microsoft .NET Framework 4 is already a part of this operating system. You do not need to install the .NET Framework 4 redistributable.
2) Same or higher version of .NET Framework 4 has already been installed on this computer.
So I Google around and find several sites that say things like '.NET Framework 4.5.2 is considered to be an "in-place update" to the .NET 4 family, with no need to recompile applications' and I think maybe I can just install the .Net 4.5.2 targeting packs and target them using this parameter with MSBuild:
/property:FrameworkPathOverride="C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.5.2"
Sure enough, this seems to work. The problem is I don't fully understand reference assemblies and targeting packs and whatnot. I'm concerned that, while it seems I may have solved the problem, I will discover later on, much farther down the road, that I have introduced some other nasty issue.
I failed to mention I also tried to install the .Net Framework 4.0.3 milti-targeting pack via this link but I get the following error:
Microsoft .NET Framework 4 Multi-Targeting Pack was not found. Please repair your installation for Microsoft Visual Studio 2010 in order to get this update.
I would not recommend you continue using FrameworkPathOverride. This is changing your application to compile as if it were .NET 4.5.2, not 4.0. There will be unintended consequences.
You can download the .NET Framework 4.0 targeting pack here: https://www.microsoft.com/en-us/download/details.aspx?id=29052
Or, you can download the .NET 4.0 targeting pack with the Visual Studio 2017 installer by selecting it in "Individual Components".
The problem is I don't fully understand reference assemblies and targeting packs and whatnot.
"Reference assemblies" are basically like header files in .NET. When you compile an application for .NET Framework 4.0, you "targeting" the APIs that are available in .NET 4.0 runtime. This forms the minimum runtime version that your application can run on. However, the application will execute on the version of the .NET Framework runtime which is installed on the machine (it's a global, shared version), which will almost certainly be newer than 4.0.
Installing the targeting pack just means you are installing a copy of the 'header files' to your machine. Your machine will still have .NET Framework 4.5.x or 4.6 runtime installed.
As .NET 4.0 is out of support and most machines will have 4.5.2 or newer, you should consider compiling against .NET Framework 4.5.2 instead. You can do this from the project properties page in Visual Studio. Or, you can edit the csproj file.
If you're using the "classic", more verbose csproj format, that will be like this
<PropertyGroup>
<TargetFrameworkVersion>v4.5.2</TargetFrameworkVersion>
</PropertyGroup>
If you're using the "new", slimmer csproj for VS 2017, that will be
<PropertyGroup>
<TargetFramework>net452</TargetFramework>
</PropertyGroup>