We have been using TFS 2015 with great success for a couple years now. This includes the new build system where we can use the built in build tasks. For example, the typical Visual Studio project build definition includes the following tasks:
These worked great until we tried to build a solution which included .NET Core/Standard projects.
core\core.csproj(1,1): Error MSB4041: The default XML namespace of the project must be the MSBuild XML namespace. If the project is authored in the MSBuild 2003 format, please add xmlns=”http://schemas.microsoft.com/developer/msbuild/2003″ to the <Project> element. If the project has been authored in the old 1.0 or 1.2 format, please convert it to MSBuild 2003 format.
The root cause of this error is that we are trying to use the VS2015 MSBuild tools to build a solution which includes a .NET Standard project. The .NET team changed the project file structure (first announced here) for new .NET Core and .NET Standard projects along with the release of Visual Studio 2017. For example, the first screenshot below shows the root XML node for a traditional full .NET Framework class library.
This is the new format for a .NET Standard class library.
The old build tools require the first structure which has the Project root node. Support for building .NET Core/Standard came with the TFS 2017 Update 2 update.
.NET Core tasks support project files
With the current update, we are enhancing .NET core tasks to support *.csproj files in addition to project.json. You can now use Visual Studio 2017 on your build agents to build .NET core applications using csproj files.
We are specifically using TFS 2015 Update 2.1 which is version 14.95.25229.0. We don’t currently have bandwidth to update it anytime soon but need to be able to build these new project types.
TFS/VSTS (even the older versions) are very flexible tools. In general, if you can perform a task on the commandline you can also do it in TFS/VSTS. The experience isn’t quite as nice as the built in tasks we previously used but we got it working with relative ease and it allows us to use the latest versions of .NET until we update TFS. The rest of this post will walk through the steps we took to accomplish this.
First we need the tools capable of building these new project types. Previously this required installing Visual Studio on the build agent which was always painful and just felt dirty. Microsoft now makes the build tools available for download in a standalone install:
Once this is installed on the build agent you can access the new version of msbuild.exe at the following location:
“c:\Program Files (x86)\Microsoft Visual Studio\2017\BuildTools\MSBuild\15.0\Bin\msbuild.exe”
With these tools installed, we can now use the Batch Script task in our build definition to run msbuild.exe with the “/t:restore /p:RestoreIgnoreFailedSources=true” arguments to restore the Nuget packages referenced in the new project files.
Without this step you will likely see the following error:
C:\Program Files\dotnet\sdk\2.0.2\Sdks\Microsoft.NET.Sdk\build\Microsoft.PackageDependencyResolution.targets(323,5): error : Assets file ‘c:\Program Files\TFS2015Agent\_work\42\s\core\obj\project.assets.json’ not found. Run a NuGet package restore to generate this file. [c:\Program Files\TFS2015Agent\_work\42\s\core\core.csproj]
Build continuing because “ContinueOnError” on the task “ReportAssetsLogMessages” is set to “ErrorAndContinue”.
The command above only supports restoring Nuget packages for the new build project types. We also need to restore packages listed in the packages.config file as well. For that we can run the nuget.exe command in a Batch Script task. These are the Nuget packages for traditional projects.
Notice the “Agent.HomeDirectory” build variable used in the path of the task. This is a built-in variable with the TFS agent home directory. The nuget.exe command is provided in the tools of the TFSAgent which is nice.
Finally, we can compile the code using msdeploy.exe from the VS2017 Build Tools.
And that’s it. Now we can successfully restore and compile a solution with a mix of Full .NET, .NET Core and .NET Standard frameworks from an old install of TFS 2015.
I hope this was post was helpful to you. If so please add a comment below to let me know or ask any further questions you might have.