One of the components updated for the Visual Studio 2017 release is the MSBuild build system. With the move of the .NET Core’s project system from project.json to the csproj format, MSBuild was updated to support the new lightweight csproj files. It also provides a better NuGet support, supporting referencing of the NuGet packages directly from csproj, and introducing restore and pack build tasks. This tasks can be used to restore project’s NuGet dependencies and to pack libraries without using NuGet, just with MSBuild.

While these features are primarily advertised (and work out of the box) for .NET Core projects, they can be used with .NET Framework 4.x projects too, assuming you have Visual Studio 2017 installed.

Restore

Restore task invocation is simple and is equivalent to the NuGet restore command

msbuild "path" /t:restore

If you will try to execute the command for an existing .NET Framework project with some NuGet packages referenced, it will do nothing. The exact message is “Nothing to do. None of the projects specified contain packages to restore”. MSBuild restore does not recognize packages.config. Instead, it expects to see all the NuGet references inside of the .csproj files.

This feature can be enabled via the NuGet Package Manager options. You may need to remove and add again referenced packages to switch csproj to the new way of referencing packages.

NuGet options

As the result, the MSBuild should be able to perform the restore command successfully.

Pack

MSBuild pack command is the direct replacement for the NuGet pack. While MSBuild still supports .nuspec files, it can also build the package based on the project properties, or the command line parameters, without spec.

Similar to the restore command, pack does not work out of the box for .NET Framework projects. To support this command, some MSBuild tasks need to be imported in the project. It is done automatically for the .NET Core projects, but requires some modifications in csproj for the .NET Framework projects.

First change is to import NuGet related build tasks.

<Import Project="$(MSBuildSDKsPath)\NuGet.Build.Tasks.Pack\build\NuGet.Build.Tasks.Pack.targets" />

MSBuildSDKsPath variable points to C:\Program Files (x86)\Microsoft Visual Studio\2017\Enterprise\MSBuild\Sdks folder and is a part of the new MSBuild concept - SDK - which allows dynamically delivered build process extensions.

With this change, MSBuild is ready to do the pack. However, if you will try, it will complain about missing fields – ID and Authors. This fields can be defined using MSBuild properties or from the command line. For example, the command line may look like

msbuild /t:pack /p:PackageId=MSBuildTestLib /p:Authors="Andrei Marukovich"

And when defined in csproj

<PropertyGroup>
    <PackageId>MSBuildTestLib</PackageId>
    <Authors>Andrei Marukovich</Authors>
    <BuildOutputTargetFolder>lib\net461</BuildOutputTargetFolder>
</PropertyGroup>

BuildOutputTargetFolder is a property which should be used in this case to instruct MSBuild which framework folder to use for the build output. Without this line, the project assemblies will go in the root of .nupkg \lib folder. For the additional information about using the MSBuild properties for controlling the packing process and defining the package metadata, see Additions to the csproj format for .NET Core.

After these final changes, the modified .NET Framework project will allow to restore the packages and to be packed as a NuGet package using MSBuild, without involving NuGet.exe, and will continue to work in Visual Studio 2017.

blog comments powered by Disqus