MSBuild使用错误版本的sgen.exe生成XmlSerializer dlls?

6
我正在使用TeamCity运行一个MSBuild脚本来清理和重建我们的解决方案之一。当我部署此过程构建的dll时,Web服务器会返回一个关于[MyType].XmlSerializer.dll的错误,指出“该程序集是由一个比当前加载的运行时更新的运行时构建的,因此无法加载。” 我目前的笔记如下:
  • 该解决方案是一个 Visual Studio 2010 解决方案,目标为 .Net Framework 3.5。
  • TeamCity设置为模拟这个。 它设置了 MSBuild 版本 - “.Net Framework 4.0” 和 MSBuild ToolsVersion - “3.5”。 这告诉TeamCity使用MSBuild 4.0,但针对3.5框架。 因为我们使用Visual Studio 2010,所以必须使用MSBuild 4.0,否则会产生其他错误(与VS2010使用的新警告代码相关)。 这似乎正常工作,并为大多数dll生成 .Net 3.5的dll。
  • MSBuild进程调用resgen.exe和sgen.exe来分别生成资源文件和XmlSerializer文件。 由于我们使用的是MSBuild 4.0,它会查找Windows SDK 7.1。 我已经安装了那个版本。 我还安装了Windows SDK 7.0。
  • 无论我选择什么框架,构建过程都会调用WinSDK 7.1下的 sgen.exe 并生成 .Net Framework 4.0 的[MyType].XmlSerializer.dll文件。 这是否正确?

就我所知,我的选择如下:

  • 如果我更改为针对旧版本的 v3.5 MSBuild 工具,则VS2010已在解决方案文件中放置警告,MSBuild 3.5无法识别并破坏构建。 这不是一个真正的选择。
  • 尝试更改注册表中的路径到工具(如本主题中所讨论的),我没有看到任何更改。
  • 在服务器上安装VS2010。 显然,VS2010使用了一种中间的 WinSDK,即v7.0A,而获得该选项的唯一方法是在服务器上安装VS2010。 这不是一个真正的选择。
  • 更改项目以不生成XmlSerializer.dlls。 这个方法可行,但似乎有点牵强,因为它并未真正解决问题,我也担心性能影响。

我有遗漏的吗? 有其他选择吗?

3个回答

6

尝试设置名为SGenToolPath的属性,以使用您想要使用的SGen工具。

Microsoft.Common.targets文件像这样调用SGen任务:

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

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

  </SGen>

我模糊地记得在64位构建时需要这样做。如果您有任何问题,请添加评论。


说句实话,将 /v:diag 添加到 MSBuild 命令行执行中,应该会显示正在使用的 SGEN 路径。 - Ritch Melton
1
它正在64位平台上构建。我希望它能够自动正确地选择框架,但是没关系。像你建议的那样,在项目文件中设置SGenToolPath后,我能够修复它。在项目文件中,它看起来像这样:<GenerateSerializationAssemblies>Auto</GenerateSerializationAssemblies><SGenToolPath>C:\Program Files\Microsoft SDKs\Windows\v7.0\bin</SGenToolPath>。我还必须确保在Debug和Release配置中都设置了它。谢谢。 - Brian Ellis
是的,我认为我加入了一个x64属性组来处理它。很高兴我能帮忙。 - Ritch Melton
1
原来你可以直接在.csproj文件中指定SDK的路径:我添加了<TargetFrameworkSDKToolsDirectory>C:\Program Files (x86)\Microsoft SDKs\Windows\v10.0A\bin\NETFX 4.6 Tools</TargetFrameworkSDKToolsDirectory>,然后构建就能找到lc.exe了。我之前期望使用<SdkToolsPath>来设置,但那样行不通。上面的答案表明SdkToolsPath是从TargetFrameworkSDKToolsDirectory设置的,所以我尝试了一下,结果成功了。这是在Visual Studio 2015上,通过ant调用msbuild实现的。 - TomEberhard
在我的电脑上,好的 sgen 路径是 "C:\Program Files\Microsoft SDKs\Windows\v6.0A\bin"。路径可能取决于安装的 SDK。 - nmariot

1
Windows SDK的安装程序问题历史不太美好。请查看此答案以获取正确的注册表项。

我已经修复了这些路径,但似乎没有任何改变。它仍然调用的是4.0版本的sgen.exe而不是3.5版本的sgen.exe。 - Brian Ellis

0
在我的电脑上,我发现正确的版本被调用了 C:\Program Files (x86)\Microsoft SDKs\Windows\v7.0A\bin\sgen.exe,但目标DLL不正确。
我认为这是由于我的 sgen.exe.config 导致的,删除以下行有助于解决我的问题。
<startup useLegacyV2RuntimeActivationPolicy="true">
        <supportedRuntime version="v4.0"/>
        <supportedRuntime version="v2.0.50727"/>
    </startup>

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