Error 0x80131040 “The located assembly’s manifest definition does not match the assembly reference” when I use a Windows Runtime class written in C# from my C++/WinRT project

Raymond Chen

Raymond

So you’re writing your C++/WinRT project, and everything is going swimmingly. There’s some code written in C# that you’d rather not port to C++/WinRT, just use as-is. “No problem,” you say. “I can just package the C# code as a Windows Runtime class, and then I can use the inter-language features of the Windows Runtime to allow the C# code to be consumed by C++/WinRT.”

You add the C# code as a project alongside your C++/WinRT project, you add a reference from the C++/WinRT project to the C# project, and everything builds: It’s a miracle!

Except that when you actually try to use the C#-written Windows Runtime class, you get error 0x80131040: The located assembly’s manifest definition does not match the assembly reference.

What’s going on, and more importantly, how do I fix it?

Here’s what’s going on: Visual Studio checks the Min version of the C# project. This version controls which version of .NET Core and .NET Native are used. In mixed-language scenarios, such as we have here with C++/WinRT and C#, Visual Studio defaults to .NET Core 1.1 and .NET Native 1.4. However, if the minimum version is set to Windows 10 version 1709 (Build 16299) or higher, then Visual Studio copies the .NET Core 2 libraries into the application output folder and tries to run them against .NET Core 1.1.

That is the version mismatch that’s being reported. The mismatch is not with the version of your C# component. The mismatch is with the version of .NET Core.

The workaround is to set your C# component’s minimum version to Windows 10 version 1703 (Build 15063) or lower: From your C# project, go to Properties, Library, and under Targeting, set the Min version to Windows 10 Creators Update (10.0; Build 15063) or lower.

My colleague Johan Laanstra found another workaround, which has been shared by another colleague Alexander Sklar:

  1. Right click on the VCXProj file → Manage NuGet Packages.
  2. Search for Microsoft.Net.Native.Compiler, and install it.
  3. Then add the following properties to the VCXProj
<PropertyGroup>
  <UseDotNetNativeToolchain Condition="'$(Configuration)'=='Release'">true</UseDotNetNativeToolchain>
  <DotNetNativeVersion>2.2.3</DotNetNativeVersion>
</PropertyGroup>

And it looks like Carcadio Garcia found a different, lengthier workaround, which I haven’t tried.

Bonus chatter: Tom McDonald informed me that Carcadio Garcia’s workaround has not been updated for Visual Studio 16.6, which uses different directories from earlier versions of Visual Studio. Support for Visual Studio 16.6 can be found in this sample project. He also shared with me some cute little tables. Here’s one of them:

Microsoft.NETCore.Universal­Windows­PlatformVisual StudioDot­Net­Native­VersionDot­Net­Native­Shared­Library
6.2.10 (current)16.62.2.8-rel-28605-002.2.27912.00
6.2.916.52.2.7-rel-27913-002.2.27912.00

There’s also an issue with where the NuGet packages are kept. They could be kept in the user’s private NuGet package store or in the Visual Studio global package store. The danger of using the user’s private NuGet package store is that the user might not have the package. The danger of using the Visual Studio global package store is that the contents of that store are not contractual and can change at the next update.

NugetPathVisual StudioSample project
$(ProgramFiles)\Microsoft SDKs\UWP­NuGet­Packages≥ 16.6Sample
$(USERPROFILE)\.nuget\packages≤ 16.5Sample

One trick is to create a blank C# UWP app targeting the matching version of the Microsoft.NETCore.Universal­Windows­Platform meta-package and build it. That will restore all of the packages into the user’s private package store so that other projects can consume them.

4 comments

Comments are closed.

  • Avatar
    cheong00

    Or is it possible to run everything with .NET Core 2 runtime instead?

    Pushing it back to run with on .NET Core 1.1 sounds like delaying a problem you would have to deal with later.

    I’ll add that the .NET Core thing has caused me headache multiple times. Why can’t they leave those without the need to run things on multi-platform continue using full version of .NET framework, and make those who need multi-platform access to tolerate the pain? (I’m referring to the fact that on .NET v5 onwards, everything has to run on .NET Core runtime and there will no longer be a “full” Windows-only version)

    Also, if the C++ side runs on .NET Core 2, will the problem fix itself? AFAIK .NET v4 can sideload v2 assembly without problem provided v4 runtime loads before v2.