SGEN:尝试使用不正确的格式加载程序集。

65

我有一个项目,在本地机器上可以很好地构建,但是当我让TFS来构建时,我收到了以下错误消息 -

SGEN:尝试使用不正确的格式加载程序集:

在阅读了许多其他相关帖子后,大多数人只说我需要将构建类型更改为x86或任何CPU,而不是x64,但是经过无数次尝试,这并不是解决方案。我的程序也是一个Windows服务,因此设置应用程序池以允许32位应用程序(如他人建议的)也不是解决方案。

15个回答

55

我今天遇到了同样的问题。一个项目在我的电脑上无法构建,但在其他电脑上可以正常构建。

最终我通过以下方法解决了这个问题:

右击出错的项目,进入属性

选择“生成”选项卡,然后找到最后一个选项,“生成序列化程序集” 我将其设置为关闭,现在项目可以成功构建。


我运行了我的项目-它运行得很好。10分钟后我重新运行,但是出现了一个错误。您的解决方案对我有用,但是关闭“生成序列化程序集”会有什么副作用? - Percy
据我所知,启用此选项将加快启动时间,特别是当您使用 [serializable] 属性时,编译器将在编译时生成序列化程序集。实质上,它会调用 SGen 提前生成序列化程序集,然后可以与应用程序一起部署。这样可以避免 XmlSerializer 每次应用程序启动时均需要生成这些序列化程序集的情况发生。 - Dave Oakley
1
我将其设置为“自动” - 现在项目构建正常!谢谢! - Jettero

18

这篇文章http://aplocher.wordpress.com/2012/10/12/sgen-an-attempt-was-made-to-load-an-assembly-with-an-incorrect-format-tfs-2010/解决了我的问题。

为了防止该页面在未来消失,以下是所涉及的步骤:

  1. 在“团队资源管理器”中,右键单击您的构建定义,选择“打开进程文件位置”。
  2. 双击所选的XAML文件。
  3. 在设计器中,选择名为“Sequence”的容器(这是包含所有其他内容的顶级容器)。
  4. 在参数列表中(通常在底部),将MSBuildPlatform从Microsoft.TeamFoundation.Build.Workflow.Activities.ToolPlatform.Auto更改为Microsoft.TeamFoundation.Build.Workflow.Activities.ToolPlatform.X86。
  5. 保存并关闭该文件。
  6. 将文件退回到TFS并再次尝试构建。

这个问题在我使用旧版解决方案和TFS2012时得到了解决。最终,我为有问题的解决方案创建了一个传统的构建模板。 - mstaffeld
1
我的调试版本构建没问题,但发布版本构建出了问题(尽管它们都使用同一个进程文件);做了这个以后,问题解决了,谢谢。 - João Portela
3
感谢您包含了相关步骤;那个 WordPress 博客已不再可用。 - Micteu
3
使用“生成序列化程序集=ON”且引用标准程序集的程序集以Debug/AnyCPU构建时,我得到了这个.NET Standard错误。当我将其更改为“自动”时,错误消失了。 - James White
2
它已经消失了,除非你去wayback https://web.archive.org/web/20130208032854/http://aplocher.wordpress.com/2012/10/12/sgen-an-attempt-was-made-to-load-an-assembly-with-an-incorrect-format-tfs-2010/ - Kirk Kuykendall

12
在我搜索特定关键词时,这个问题仍然是谷歌的首选,因此,如果有人发现它有关,请发布这篇文章。
在我的情况下,我的项目在“debug”下构建得很好,但在“release”模式下却出现了OP的错误。在本主题中的任何解决方案都没有解决这个问题。
然而,在另一个论坛上,我遇到了一个晦涩的评论,说Web服务引用会干扰构建过程。 一盏灯泡亮起来了。 我的项目有许多不再使用的旧版Web服务引用。 因此,我将它们删除了。 不出所料,我现在可以在“release”模式下构建该项目,而无需禁用程序集序列化或修改CSPROJ,也无需在Azure DevOps / VSTS中玩弄SGEN引用。
希望这可以为某人节省时间。

2
不是所有的英雄都穿着斗篷! - Murphybro2

12

1
这是我在批处理文件添加x32程序集后解决失败问题的解决方案。 - Dave
1
我需要安装哪个组件?最新的Windows SDK有15个不同的组件,总共2.7GB。我宁愿只在所有构建服务器上安装所需的组件。我尝试仅安装“.Net Framework 4.7.1软件开发工具包”,但仍然出现错误:( - deadlydog
@deadlydog 我不知道需要哪些组件。如果你能单独列出并在这里发布答案,那就太好了。 - Louis Somers

12

我发现这个问题很相关: https://github.com/dotnet/sdk/issues/1630

在等待这个问题被未来版本修复的同时,我按照https://github.com/joperezr的建议,在csproj文件中添加了两个目标以解决这个问题:

<Target Name="RemoveDesignTimeFacadesBeforeSGen" BeforeTargets="GenerateSerializationAssemblies">
    <ItemGroup>
    <ReferencePath Remove="@(_DesignTimeFacadeAssemblies_Names->'%(OriginalIdentity)')" />
    </ItemGroup>
    <Message Importance="normal" Text="Removing DesignTimeFacades from ReferencePath before running SGen." />
</Target>

<Target Name="ReAddDesignTimeFacadesBeforeSGen" AfterTargets="GenerateSerializationAssemblies">
    <ItemGroup>
    <ReferencePath Include="@(_DesignTimeFacadeAssemblies_Names->'%(OriginalIdentity)')" />
    </ItemGroup>
    <Message Importance="normal" Text="Adding back DesignTimeFacades from ReferencePath now that SGen has run." />
</Target>

这是我们解决问题的方法(当Debug可以工作但Release不能)。 - Austin Salgat
这个方法在我本地构建时有效,但当我在构建服务器上运行时,它并没有解决问题。然而,我还从@TDN(上面)那里添加了SGenToolPath修复程序,最终成功构建。所以也尝试一下这个选项吧! - Quango
使用4.7.2版本,在csproj中设置目标,同时使用SGenToolPath也无法解决问题。 - toebens
你的回答真的救了我一天。我不得不进行了一点扩展-https://dev59.com/U2Yr5IYBdhLWcg3w0tWE#64474637。以防其他人遇到同样的问题。 - mark

8

当我尝试在Release模式下编译我的项目(平台目标设置为x86)时,我遇到了相同的错误。在Debug模式下编译是没问题的。后来我发现,在Release模式下,会运行生成序列化程序集;因此会调用SGen实用程序。问题在于MSBuild针对我的x86 EXE调用了x64版本的SGen,导致出现错误。我必须传递这个MSBuild参数,以便MSBuild使用正确版本的SGen:

/p:SGenToolPath="C:\Program Files (x86)\Microsoft SDKs\Windows\v7.0A\Bin\NETFX 4.0 Tools"

你是怎么知道叫哪个版本的SGEN的? - Peter
我想我能从构建输出中看到。对不起,这已经有一段时间了! - TNV
啊,如果你往上滚一点,就能看到了。 - Peter
谢谢,这对我来说是最有帮助的答案。然而,我要指出我的TFS发布在x86上无法构建,所以我改变了我的构建定义来使用x64。 我知道我向我的解决方案中添加了一个新的32位dll。你知道为什么它能用x64构建而不能用x86构建,出现SGEN错误吗? - Harry
2
我有相反的问题。我的平台目标是x64,但VS和MSBuild坚持使用x86工具(如SGen)。 - Keith Robertson
我从构建日志中获取了当前路径,并附加了/x64,在我的情况下它变成了/p:SGenToolPath="C:\Program Files (x86)\Microsoft SDKs\Windows\v10.0A\bin\NETFX 4.6.1 Tools\x64"。 - mhenry1384

7
我的回答是对ola-eldøy的补充。在我的情况下,我必须排除更多的程序集,因为它们每个都会产生相同可怕的错误。
Could not load file or assembly bla-bla-bla or one of its dependencies. Reference assemblies should not be loaded for execution.  They can only be loaded in the Reflection-only loader context. (Exception from HRESULT: 0x80131058)

因此,我的解决方案是扩展ola-eldøy的代码并将其保存在Directory.Build.targets中:
<Project>
  <ItemGroup>
    <ReflectionOnlyAssemblyNames Include="Microsoft.Bcl.AsyncInterfaces"/>
    <ReflectionOnlyAssemblyNames Include="System.Buffers"/>
    <ReflectionOnlyAssemblyNames Include="System.Numerics.Vectors"/>
    <ReflectionOnlyAssemblyNames Include="System.Runtime.CompilerServices.Unsafe"/>
  </ItemGroup>
  <Target Name="RemoveDesignTimeFacadesBeforeSGen" BeforeTargets="GenerateSerializationAssemblies">
    <ItemGroup>
      <_ReflectionOnlyAssembly_Names Include="@(_ReferencePath_Names)"
                                     Condition="'@(ReflectionOnlyAssemblyNames)' == '@(_ReferencePath_Names)' And '%(Identity)' != ''"/>
    </ItemGroup>
    <ItemGroup>
      <ReferencePath Remove="@(_DesignTimeFacadeAssemblies_Names->'%(OriginalIdentity)')" />
      <ReferencePath Remove="@(_ReflectionOnlyAssembly_Names->'%(OriginalIdentity)')" />
    </ItemGroup>
    <Message Importance="normal" Text="Removing DesignTimeFacades from ReferencePath before running SGen." />
  </Target>
  <Target Name="ReAddDesignTimeFacadesBeforeSGen" AfterTargets="GenerateSerializationAssemblies">
    <ItemGroup>
      <ReferencePath Include="@(_DesignTimeFacadeAssemblies_Names->'%(OriginalIdentity)')" />
      <ReferencePath Include="@(_ReflectionOnlyAssembly_Names->'%(OriginalIdentity)')" />
    </ItemGroup>
    <Message Importance="normal" Text="Adding back DesignTimeFacades from ReferencePath now that SGen has run." />
  </Target>
</Project>

1
谢谢Mark,当我针对Framework 4.8时,需要像上面那样排除额外的程序集。 - Henry Barker

5
在我的情况下,这个错误不是因为x86 / x64设置的组合无效,而是由于尝试构建一个针对特定.NET框架版本(v4.5.1)的项目,但该版本参考程序集未安装在构建服务器上。以下两个条件的组合导致了错误:
1. 在Visual Studio中,在项目属性页面的应用程序选项卡上,“目标框架”设置为“.NET Framework 4.5.1”; 2. 在构建服务器上,在文件夹“C:\ Program Files(x86)\ Reference Assemblies \ Microsoft \ Framework \ .NETFramework”中,名为v4.5.1的文件夹不存在。(其他带有版本号的文件夹,包括v3.5、v4.0和v4.5,存在。)
解决方法是在构建服务器上安装Windows Software Development Kit (SDK) for Windows 8.1。在安装向导中,在“选择要安装的功能”步骤中,我取消了除“.NET framework 4.5.1 Software Development Kit”之外的所有复选框。
运行该安装程序将导致缺失的Reference Assemblies \ Microsoft \ Framework \ .NETFramework文件夹中的v4.5.1文件夹被创建,并且构建成功运行。

1
对我来说也是一样。我安装了Microsoft Build Tools 2015。它修复了引用程序集和sgen问题。 - Der_Meister

2

根据@james-white的批准答案中的一个评论,以下方法对我有效:

在项目文件中将GenerateSerializationAssemblies属性从"On"更改为"Auto"

想将这个建议整理成答案,让那些只是浏览的人更明显地看到。谢谢James White


这对我来说神奇地起作用了。谢谢! 但是我到底做了什么? - user1034912

1
我遇到了类似的问题,当在VS或通过命令行MSBuild构建时,看到SGEN“格式不正确”的错误。我的项目是x64,但MSBuild坚持使用32位版本的工具。(我的一些同事通过在VS 2015中构建来解决此问题,但我只安装了VS 2017,并希望保持这种状态。)
查看诊断构建输出,看起来SGEN是从其SdkToolsPath参数命名的目录中运行的(对我来说:C:\Program Files (x86)\Microsoft SDKs\Windows\v10.0A\bin\NETFX 4.6.1 Tools\)。这是从TargetFrameworkSDKToolsDirectory分配的。查看目标文件,这来自SDK40ToolsPath。而且这是从MSBuild的.config文件设置的。
我通过编辑C:\Program Files (x86)\Microsoft Visual Studio\2017\Professional\MSBuild\15.0\Bin\MSBuild.exe.config(需要管理员权限)解决了这个问题,使用设置SDK40ToolsPath属性。
<property name="SDK40ToolsPath" value="$([MSBuild]::GetRegistryValueFromView('HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Microsoft SDKs\NETFXSDK\4.6.2\WinSDK-NetFx40Tools-x64', 'InstallationFolder', null, RegistryView.Registry32))" />

(注意:如果您正在寻找64位操作系统上的注册表中的此路径,请转到HKLM \ SOFTWARE \ WOW6432Node \ Microsoft ...)
主要更改是从x86到x64以使用64位工具。 我还更改了框架,以便使用我们所使用的框架(4.6.2)。 这可能意味着我们只能可靠地使用64位项目和此框架的工具,有了这个更改。 尽管如此,我希望这可能会帮助遇到此问题的人。 (我震惊并沮丧MSBuild不会根据框架和体系结构自动更改工具路径。)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接