Costura: Using the `dotnet msbuild` command produces invalid executables for apps targeting .NET Framework

After upgrading our TeamCity installation, I followed JetBrains recommendataion to migrate from their Visual Studio (sln) runner to the new .NET runner. This basically means running dotnet msbuild instead of MSBuild.exe. Also, simply installing the .NET 5 SDK without having to deal with the complexity of Visual Studio Build Tools installation on the build agent seemed very appealing.

So I started to try building apps with dotnet msbuild instead of the usual MSBuild.exe command but had a very unpleasant surprise. The first app I tried was crashing at startup before even hitting the module initializer. The event viewer was showing a crash but without much usable details. When removing Costura, the app would stop crashing. So I enabled fusion logs to try to understand what was happening and saw something very unexpected for a .NET Framework app: a reference to System.Private.CoreLib! (This is basically the .NET Core equivalent of mscorlib.)

Here is how to reproduce the problem with a minimal hello world app.

Program.cs:

using System;

namespace hellocostura
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("Hello World!");
        }
    }
}

hellocostura.csproj:

<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <OutputType>Exe</OutputType>
    <TargetFramework>net48</TargetFramework>
  </PropertyGroup>

  <ItemGroup>
    <PackageReference Include="Costura.Fody" Version="5.2.0" PrivateAssets="all" />
  </ItemGroup>

</Project>

assemblyrefs.csx (to check what are the referecend assemblies, runnable with the dotnet script global tool):

#r "nuget: dnlib, 3.3.2"

using (var stream = System.IO.File.OpenRead(Args[0]))
using (var module = dnlib.DotNet.ModuleDefMD.Load(stream))
{
    Console.WriteLine(string.Join("\n", module.GetAssemblyRefs()));
}

✅ When building with the standard msbuild exectuable, the hellocostura.exe has references to mscorlib and System, everything is fine.

rm -rf bin obj && \
  dotnet restore --nologo --verbosity=quiet && \
  msbuild -nologo -verbosity:quiet && \
  dotnet script assemblyrefs.csx bin/Debug/net48/hellocostura.exe
mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089

❌ When building with the dotnet msbuild command, the hellocostura.exe has references to mscorlib and System.Private.CoreLib, leading to the crash at startup.

rm -rf bin obj && \
  dotnet restore --nologo --verbosity=quiet && \
  dotnet msbuild -nologo -verbosity:quiet && \
  dotnet script assemblyrefs.csx bin/Debug/net48/hellocostura.exe
mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
System.Private.CoreLib, Version=5.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e
System.IO.Compression, Version=5.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
System.Runtime, Version=5.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a

Note: the only difference bewtween the two commands is msbuild vs dotnet msbuild.

I will investigate this issue and hopefully be able to provide a workaround, maybe even another pull request. 😉

About this issue

  • Original URL
  • State: closed
  • Created 3 years ago
  • Comments: 17 (17 by maintainers)

Commits related to this issue

Most upvoted comments

Stable version should be available now!