Msbuild: SGen doesn't work with reference assemblies (?)

Created on 7 Nov 2017  ·  26Comments  ·  Source: dotnet/msbuild

Steps to reproduce

  1. Create a new Windows Classic Console App in VS 15.3 or newer
  2. Unload the project and add these package references to the .csproj:
  <ItemGroup>
    <PackageReference Include="MassTransit.RabbitMQ">
      <Version>3.5.6</Version>
    </PackageReference>
    <PackageReference Include="Microsoft.Extensions.DependencyInjection">
      <Version>1.1.0</Version>
    </PackageReference>
  </ItemGroup>
  1. Set this property:
    <GenerateSerializationAssemblies>On</GenerateSerializationAssemblies>
  1. Reload the project and build.

Expected behavior

Should build.

Actual behavior

Severity    Code    Description Project File    Line    Suppression State
Error       An attempt was made to load an assembly with an incorrect format: C:\Users\kirillo\.nuget\packages\System.Net.Http\4.3.0\ref\net46\System.Net.Http.dll. DanTupRepro C:\Users\kirillo\Documents\Visual Studio 2017\Projects\DanTupRepro\SGEN     

Environment data

msbuild /version output:
15.3.409.57025

Most helpful comment

I've submitted a ticket in the SDK:
https://github.com/dotnet/sdk/issues/1630
and proposed a work around that we use in my company.

All 26 comments

The detailed error also contains a more specific explanation:

Reference assemblies should not be loaded for execution. They can only be loaded in the Reflection-only loader context. (Exception from HRESULT: 0x80131058)

We've hit this after migrating to PackageReference - MSBuild now passes additional DLLs (including some ref assemblies) to sgen. This means in many cases, switching to PackageReference may require disabling generation of serialisation assemblies (which could be an extra risk, relying on them to be created at runtime, as well as a perf hit).

To add furtehr confusion, with GenerateSerializationAssemblies set to Auto (the default), this happens to us in Release builds but not Debug (both configs are set to Auto). I don't know if auto means "on for release builds and off for debug builds" but it seems to behave that way for our project at least!

I don't know if auto means "on for release builds and off for debug builds"

It does:

<_SGenGenerateSerializationAssembliesConfig>$(GenerateSerializationAssemblies)</_SGenGenerateSerializationAssembliesConfig>
<_SGenGenerateSerializationAssembliesConfig Condition="'$(ConfigurationName)'=='Debug' and '$(_SGenGenerateSerializationAssembliesConfig)' == 'Auto'">Off</_SGenGenerateSerializationAssembliesConfig>

https://github.com/microsoft/msbuild/blob/master/src/Tasks/Microsoft.Common.CurrentVersion.targets#L3429-L3431

@radical Aha, thanks! I did Google for an answer but turned up nothing. Strange that if that's what it does that my csproj have separate elements for this setting in both Release and Debug both set to Auto by default - if the default is on-for-release and off-for-debug, putting the values in directly would remove some confusion over what Auto means (or indeed, why it means something different depending on whether the configuration name is the magic string "Debug"!).

I've submitted a ticket in the SDK:
https://github.com/dotnet/sdk/issues/1630
and proposed a work around that we use in my company.

My company just ran into this, but only if we add a package reference to SourceLink.Embed.AllSourceFiles. With that reference, msbuild gives this:

SGEN : error : An attempt was made to load an assembly with an incorrect format: %userprofile%\.nuget\packages\system.net.http\4.3.0\ref\net46\System.Net.Http.dll

I can't tell if this is entirely related? The project itself is targeting net462 and that shouldn't change with this new package reference.

Workaround for me is ExcludeAssets="compile":

<PackageReference Include="SourceLink.Embed.AllSourceFiles" Version="2.5.0" ExcludeAssets="compile" />

Is that a bug in the package? It shouldn't be adding references to my project, only messing with build targets to pass /embed:bigfilelist to csc.exe.

This will only get more common as people move to new-style projects + NuGet. Pulling into 15.6, at least for triage so we don't forget it.

Just a "me too" comment, that we're migrating to new-style projects and we've hit this issue today - I figure we missed the 15.6 milestone for this issue. I'm going to explore disabling serialization assembly generation, but obviously I'd rather not. Cheers!

Another "me too" here. Is there any planned fix for this?

Just another “me too” comment

me too....

This is still happening for certain projects here as well, is there any other workaround besides turning off that serialization?

me too. i also met the same issue in the vs 2019, .net framework 4.7.2.
error message as below:

Severity Code Description Project File Line Suppression State
Error An attempt was made to load an assembly with an incorrect format: C:Usersey02.nugetpackagessystem.memory4.5.1refnetstandard2.0System.Memory.dll. SapTalk.Scheduler C:WorkspaceSourceCodePhase5Ey.SapTalkSapTalk.SchedulerSGEN

Me too.

same error

Severity Code Description Project File Line Suppression State
Error An attempt was made to load an assembly with an incorrect format: C:Usersey02.nugetpackagessystem.memory4.5.1refnetstandard2.0System.Memory.dll. SapTalk.Scheduler C:WorkspaceSourceCodePhase5Ey.SapTalkSapTalk.SchedulerSGEN

Well, 'me too'. We are using .net 4.7.2 and both new and old format of .csproj files in different projects. Error occurred after referencing new package.

Same issue with 4.8.

In our implementation, I was able to exclude the reference from compile.

   <PackageReference Include="Unity.Interception">
     <ExcludeAssets>compile</ExcludeAssets>
     <Version>5.11.1</Version>
   </PackageReference>

https://docs.microsoft.com/en-us/nuget/consume-packages/package-references-in-project-files

We have the problem with .net 4.7.2 in Release mode. Unfortunately we can not disable GenerateSerializationAssemblies as our assembly makes heavy use of xmlserializer + WCF. The (initial) performance drop at runtime would be too bad.

We added Stackexchange.Redis 2.0.601 to our project that is having a dependency on System.Buffers.dll and some other netstandard2.0 assemblies.

Can you please fix this ASAP?

Meanwhile, is there any other workaround?

@KirillOsenkov do you have any timeline when this problem will be solved?

@rainersigwald

Having this problem as well.

This issue was moved to dotnet/wcf#3991

I have been avoiding this by using https://stackoverflow.com/a/49253618 and blacklisting assemblies that fail in my Directory.Build.targets so that they are not passed to sgen. Added System.Buffers and System.Runtime.CompilerServices.Unsafe to my blacklist and that got me past the issue for now.

Oh, I see this was already stated in https://github.com/Microsoft/msbuild/issues/2707#issuecomment-343166372

this ticket got closed here and was moved to https://github.com/dotnet/wcf/issues/3991 and/or https://github.com/dotnet/sdk/issues/1630 but isn't that only related to .net core or .net core client wcf library?
shouldn't the problem/this ticket be kept open in here? as it is .net framework + msbuild related when a .net framework project makes use of any .netstandard2.0 assembly.

my bad workaround looks like this currently. i overwrote the target after the import of all usual targets like this in my .csproj file (you might want to change the regex):

```

Name="GenerateSerializationAssemblies"
Condition="'$(_SGenGenerateSerializationAssembliesConfig)' == 'On' or ('@(WebReferenceUrl)'!='' and '$(_SGenGenerateSerializationAssembliesConfig)' == 'Auto')"
DependsOnTargets="AssignTargetPaths;Compile;ResolveKeySource"
Inputs="$(MSBuildAllProjects);@(IntermediateAssembly)"
Outputs="$(IntermediateOutputPath)$(_SGenDllName)">

<PropertyGroup>
  <SGenMSBuildArchitecture Condition="'$(SGenMSBuildArchitecture)' == ''">$(PlatformTargetAsMSBuildArchitecture)</SGenMSBuildArchitecture>
</PropertyGroup>

<!-- START of sgen specific code -->
<ItemGroup>      
  <SGenReference Include="@(ReferencePath)" Condition="!$([System.Text.RegularExpressions.Regex]::IsMatch('%(Directory)', 'net461|netstandard1.3|.netstandard2.0'))" />
</ItemGroup>
<!-- <Message Text="This is my list of SGenReference files: @(SGenReference)"/> -->
<!-- SGen References is changed from @(ReferencePath) to @(SGenReference) in argument below too -->
<!-- END of sgen specific code -->

<SGen
    BuildAssemblyName="$(TargetFileName)"
    BuildAssemblyPath="$(IntermediateOutputPath)"
    References="@(SGenReference)"
    ShouldGenerateSerializer="$(SGenShouldGenerateSerializer)"
    UseProxyTypes="$(SGenUseProxyTypes)"
    KeyContainer="$(KeyContainerName)"
    KeyFile="$(KeyOriginatorFile)"
    DelaySign="$(DelaySign)"
    ToolPath="$(SGenToolPath)"
    SdkToolsPath="$(TargetFrameworkSDKToolsDirectory)"
    EnvironmentVariables="$(SGenEnvironment)"
    MSBuildArchitecture="$(SGenMSBuildArchitecture)"
    SerializationAssembly="$(IntermediateOutputPath)$(_SGenDllName)"
    Platform="$(SGenPlatformTarget)"
    Types="$(SGenSerializationTypes)">

  <Output TaskParameter="SerializationAssembly" ItemName="SerializationAssembly"/>

</SGen>


```

however this is very bad. Microsoft please come up with a real fix ASAP

this ticket got closed here and was moved to dotnet/wcf#3991 and/or dotnet/sdk#1630 but isn't that only related to .net core or .net core client wcf library?
shouldn't the problem/this ticket be kept open in here? as it is .net framework + msbuild related when a .net framework project makes use of any .netstandard2.0 assembly.

The program sgen.exe is owned by the WCF folks. They own both the .NET Framework version and any future .NET Core work. We talked to them internally and agreed to move the public bug to their repo (even though that's not where a fix would be checked in, it is at least the right people).

Was this page helpful?
0 / 5 - 0 ratings