Custom msbuild task tries to load dependency with wrong version

1

I have custom publish process which firstly merges some assemblies into one via ILRepack, then performs some other steps and finally cleans up publish directory - removes merged dependencies from APP_NAME.deps.json, relevant assemblies and symbol files.

In order to implement the last step, I've created a NuGet package with a custom MsBuild task. According to Nate's blog post, I've set PrivateAssets="All" in order to ship all task's dependencies within the package:

<ItemGroup>
    <PackageReference Include="JetBrains.Annotations" Version="2019.1.3" />
    <PackageReference Include="Microsoft.Build.Utilities.Core" Version="15.9.20" />
    <PackageReference Include="Newtonsoft.Json" Version="12.0.2" />
    <PackageReference Update="@(PackageReference)" PrivateAssets="All" />        
</ItemGroup>

Package layout looks like:

enter image description here

Suddenly, during publish, this step fails with error:

task failed unexpectedly. Could not load file or assembly 'Newtonsoft.Json, Version=12.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed'. Could not find or load a specific file. (0x80131621)

I can't understand why task tries to load version 12.0.0.0 while I have Newtonsoft.Json 12.0.2 (as specified in PackageReference).

Thank you for any help!


Updated:

According to this msbuild spec currently MSBuild tasks have serious limitations:

Tasks in MSBuild are dynamically loaded assemblies with potentially separate and colliding dependency trees. Currently MSBuild on .NET Core has no isolation between tasks and as such only one version of any given assembly can be loaded. Prime example of this is Newtonsoft.Json which has multiple versions, but all the tasks must agree on it to work.

c#
visual-studio
msbuild
nuget
asked on Stack Overflow Oct 6, 2019 by metacube • edited Oct 6, 2019 by Pod Mo

1 Answer

1
  1. As Lex Li mentioned in the comment, 12.0.2 is the NuGet package version which corresponds to the 12.0.0.0 assembly version. So the system attempts to load the right version of the assembly.
  2. According to task-isolation-and-dependencies.md, related issue etc. custom MsBuild tasks have serious limitations.
  3. MsBuild itself includes a dependency on Newtonsoft.Json 11.0.1, so custom tasks can't load any other version of this dependency.

Workarounds:

  1. Use the same dependency version as MsBuild. I guess this approach is fragile and should not be used.
  2. Create and package console application instead of a custom MsBuild task. I've chosen this approach because it is easily extensible and allows us to use any dependency version. Nate's blog post gives an overview of the approach.
  3. As Martin Ullrich mentioned in the comment, we could use task with isolation boundaries. ContextAwareTask.cs demonstrates the approach.
answered on Stack Overflow Oct 7, 2019 by metacube • edited Oct 7, 2019 by metacube

User contributions licensed under CC BY-SA 3.0