MSBuild 14 produces executable requiring older dependency than referenced

318 views Asked by At

I have a VS 2015 C# solution with a main executable and some library projects. This is a code analyzer tool, it uses Roslyn and MSBuild as well, so the main assembly requires Microsoft.CodeAnalysis and Microsoft.Build from NuGet. My recent task was to update the former package from 1.x to 2.x. It did not go fluently, but I made it work, it now requires Microsoft.CodeAnalysis 2.8.2 and Microsoft.Build 15.7.179. Everything works as expected when built from Visual Studio directly.

However, when I build the same solution (and thus the same csproj files) with MSBuild 14 from command line, the executable produced is different and crashes at runtime with the following stack, when it tries to create an MSBuild workspace:

Nem kezelt kivétel: System.Reflection.ReflectionTypeLoadException: Egy vagy több kért típus nem tölthető be. További tájékoztatást a LoaderExceptions tulajdonság lekérésével kaphat.
   a következő helyen: System.Reflection.RuntimeModule.GetTypes(RuntimeModule module)
   a következő helyen: System.Reflection.RuntimeAssembly.get_DefinedTypes()
   a következő helyen: System.Composition.Hosting.ContainerConfiguration.<>c.<WithAssemblies>b__16_0(Assembly a)
   a következő helyen: System.Linq.Enumerable.<SelectManyIterator>d__17`2.MoveNext()
   a következő helyen: System.Composition.TypedParts.TypedPartExportDescriptorProvider..ctor(IEnumerable`1 types, AttributedModelProvider attributeContext)
   a következő helyen: System.Composition.Hosting.ContainerConfiguration.CreateContainer()
   a következő helyen: Microsoft.CodeAnalysis.Host.Mef.MefHostServices.Create(IEnumerable`1 assemblies)
   a következő helyen: Microsoft.CodeAnalysis.Host.Mef.DesktopMefHostServices.get_DefaultServices()
   a következő helyen: Microsoft.CodeAnalysis.MSBuild.MSBuildWorkspace.Create(IDictionary`2 properties)
   a következő helyen: Columbus.CSAN.RoslynParser.AbstractOpen..ctor(String path, String configuration, String platform)
   a következő helyen: Columbus.CSAN.RoslynParser.FileOpen..ctor(String path, String config, String platform)
   a következő helyen: Columbus.CSAN.RoslynParser.AbstractOpen.CreateInstance(String path, String configuration, String platform)
   a következő helyen: Columbus.CSAN.MainProgram.Main(String[] args)

Looking at the LoaderExceptions property I found the following:

A(z) "System.Collections.Immutable, Version=1.2.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" fájl vagy szerelvény, illetve annak egyik függősége nem tölthető be. A megtalált szerelvény jegyzékdefiníciója nem egyezik a szerelvény hivatkozásával. (A kivétel HRESULT-értéke: 0x80131040)

Of course it cannot find 1.2.0.0 of System.Collections.Immutable, because we require 1.3.1 (which is to raise more confusion is assembly version 1.2.1.0) in packages.config, through this chain:

Microsoft.CodeAnalysis 2.8.2
Microsoft.CodeAnalysis.CSharp.Workspaces 2.8.2
Microsoft.CodeAnalysis.CSharp 2.8.2
Microsoft.CodeAnalysis.Common 2.8.2
System.Collections.Immutable 1.3.1

The command looks like this: msbuild All.sln /t:Build /p:Configuration=Debug /p:Platform=x64 /verbosity:diagnostic

In the output of MSBuild under the problematic project's references:

System.Collections.Immutable, Version=1.2.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL
    HintPath = ..\..\packages\System.Collections.Immutable.1.3.1\lib\portable-net45+win8+wp8+wpa81\System.Collections.Immutable.dll
    Private = True

I am really out of ideas why it requires an older version of the library at runtime, because 1.2.0.0 does not appear even in the verbose build log, only 1.2.1.0 from package 1.3.1.

To clarify: I am building my own project with VS2015/MSBuild14, because it is C# 6.0 only, but want it to be able to analyze C# 7.0, that is why I am requiring Roslyn 2 and MSBuild 15 as a package.

1

There are 1 answers

1
Paulo Morgado On BEST ANSWER

Some assembly referenced by that project is referencing 1.2.0.0. You can use fuslogvw.exe or just adding a EnableLog with a DWORD value of 1 to the HKEY_LOCAL_MACHINE\Software\Microsoft\Fusion registry key.

But to solve it, you'll need to add an assembly binding redirect to your config file:

<runtime>  
    <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1" appliesTo="v1.0.3705">  
        <assemblyIdentity name="System.Collections.Immutable"  
                          publicKeyToken="b03f5f7f11d50a3a"  
                          culture="neutral" />  
            <bindingRedirect oldVersion="0.0.0.0-1.2.1.0"  
                             newVersion="1.2.1.0"/>
        </dependentAssembly>
    </assemblyBinding>  
</runtime>