1

This sample shows a .NET Core project which can be packaged into a nuget package just using dotnet pack, and when restored in another project, it integrates in the msbuild pipeline. One of the great things about this sample is it creates a nuget package that integrates with msbuild on linux, mac and Windows. However, the custom build code doesn't have dependencies on any other assemblies.

How can I adapt this sample to use code that uses a dependency?

Here are my failed attempts:

Attempt 1

I added a package reference to Newtonsoft.Json and changed the code to do some JSON serialisation. However, in the project that uses the build nuget, when I do a dotnet publish, I get the following error:

error MSB4018: The "Zip" task failed unexpectedly. [C:\git\MSBuild-Features-With-Nate-McMaster\Video-2\1-NuGet\Web.csproj]
error MSB4018: System.IO.FileNotFoundException: Could not load file or assembly 'Newtonsoft.Json, Version=10.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed'. The system cannot find the file specified. [C:\git\MSBuild-Features-With-Nate-McMaster\Video-2\1-NuGet\Web.csproj]

Additionally, if my project didn't already have a dependency on JSON.NET, adding the build nuget would unnecessarily add it.

Attempt 2

I used nuget.exe spec to create a .nuspec file. At the end of the file, I added:

<files>
  <file src="bin\Release\**" target="build" />
  <file src="build\**" target="build" />
</files>

However, both "dotnet pack" and "msbuild /t:pack" ignore the file, and nuget.exe pack fails with the error Unable to find 'bin\Release\0-WriteATask\bin\Release\'. Make sure the project has been built..

If I try nuget.exe pack Zipper.nuspec or msbuild /t:pack /p:NuspecFiles=Zipper.nuspec, they both fail with the message Value cannot be null or an empty string..

Attempt 3

I edited the nuspec to remove all of the placeholders that are normally calculated from the project (any string starting and ending with a $). Then, doing a nuget.exe pack Zipper.nuspec created a nupkg file, and the net46 folder contains Newtsonsoft.Json.dll, but the netstandard1.3 folder does not.

2 Answers 2

3

The way MSBuild loads a task assembly can make it tricky to load additional assemblies that you may depend on.

Typically, the easiest way to solve this is to ship a copy of your dependencies inside your NuGet package. But your dependencies alongside your task assembly file in the package. There may be some additional complications that require you to use AssemblyLoadContext or the AppDomain.AssemblyResolve event.

You can do this without a nuspec file by forcing MSBuild to copy your assemblies into the local build output, and then copying them into your package. Set CopyLocalLockFileAssemblies=true, and add the items to _PackageFiles

Here's an example of how to do that: https://github.com/madskristensen/BundlerMinifier/blob/3333b5c38289a247391966443370ee6f4a29bf26/src/BundlerMinifier/BundlerMinifier.csproj#L35-L47

Hopefully, this will be addressed in the future, https://github.com/Microsoft/msbuild/issues/1312, and the task assembly resolution will use the NuGet cache.

Sign up to request clarification or add additional context in comments.

1 Comment

Nate, thank you for the video and sample, and now for this answer! I developed a horrible msbuild script that packed the project (without dependencies), unzipped it, deleted the auto-generated files (except for the nuspec), applied a XSLT to the nuspec, did a dotnet publish for each TFM, then did a nuget pack on the nuspec file. The example in Mads' code is much, much better. thank you!
0

Try it with the 9.0.1 version of Newtonsoft.Json, it worked for me, all these dll load problems went away, and it still targets .NET Standard. Although I did copy all the dependencies next to the task dll, but with the 10.x version even that didn't help.

4 Comments

What platform are you running? I've only tried my task on Windows, but putting Newtonsoft.Json in the same directory as my assembly worked for me. Looking at my .NET Core SDK folder, I see that v9.0.1 is bundled with the runtime, so by using that specific version, it probably loads the runtime's copy of the dll, not the one you bundled with your assembly. I'm going to need more nuget packages to complete my build task, which aren't part of the .NET Core runtime bundle, so I really need to test.
Have a look at this repo where I demonstrate the problem: github.com/BalassaMarton/msbuild-tasks
Your sample is missing the CopyLocalLockFileAssemblies property, but even after I add it, msbuild.exe can run your example, but dotnet fails. After more than 2 hours of trying different things, I can't get it to work, so I created a bug on the .net cli. github.com/dotnet/cli/issues/7510
I don't know why it was commented out, along with the part that copies the dependencies before packing, but even if I put those back, dotnet build fails.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.