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
- [WIP] Implement a custom IAssemblyResolver for .NET Framework Trying to solve #694 — committed to 0xced/Costura by 0xced 3 years ago
- Use the assembly resolver from the module definition Use the IAssemblyResolver provided by the module definition itself instead of the default resolver when reading the Costura template with Cecil so... — committed to 0xced/Costura by 0xced 3 years ago
Stable version should be available now!