【问题标题】:How to set SGEN toolpath in Msbuild to target 3.5 framework如何在 Msbuild 中将 SGEN 工具路径设置为目标 3.5 框架
【发布时间】:2011-02-14 11:49:35
【问题描述】:

我刚刚将一个项目从 VS2008 升级到 VS2010,但我仍然以 3.5 框架为目标。

在我的项目文件中,我有一个自定义任务来运行 SGEN 以生成我的 XmlSerializers.dll。然而,正在运行的 sgen 版本以 4.0 框架为目标。结果,当我运行我的应用程序时,我收到了错误消息:

“无法加载文件或程序集 'XXXX.XXXX.XmlSerializers' 或其依赖项之一。此程序集由比当前加载的运行时更新的运行时构建,无法加载。”

Sgen 任务如下所示:

  <Target Name="AfterBuild" DependsOnTargets="AssignTargetPaths;Compile;ResolveKeySource" Inputs="$(MSBuildAllProjects);@(IntermediateAssembly)" Outputs="$(OutputPath)$(_SGenDllName)">
    <!-- Delete the file because I can't figure out how to force the SGen task. -->
    <Delete Files="$(TargetDir)$(TargetName).XmlSerializers.dll" ContinueOnError="true" />
    <SGen BuildAssemblyName="$(TargetFileName)" BuildAssemblyPath="$(OutputPath)" References="@(ReferencePath)" ShouldGenerateSerializer="true" UseProxyTypes="false" KeyContainer="$(KeyContainerName)" KeyFile="$(KeyOriginatorFile)" DelaySign="$(DelaySign)" ToolPath="$(SGenToolPath)">
      <Output TaskParameter="SerializationAssembly" ItemName="SerializationAssembly" />
    </SGen>
  </Target>

ToolPath="$(SGenToolPath)"。如何让它运行面向 3.5 的版本?

有一个类似的问题here,但对我帮助不大。

【问题讨论】:

  • 根据异常消息给最终到达这里的其他人的快速说明:如果您不需要 XmlSerializers 程序集,您可以简单地在项目的构建选项卡上禁用它的创建。
  • P.S.如果您确实将生成序列化程序集设置为“关闭”,请记住为发布和调试(或相关)配置执行此操作。

标签: visual-studio-2010 sgen


【解决方案1】:

我已通过手动将 ToolPath 配置为指向 sgen.exe 的旧(版本 2.0.50727.3038)版本来解决此问题

在我的机器上,它位于:C:\Program Files (x86)\Microsoft SDKs\Windows\v7.0A\Bin

我将 ToolPath 属性更改为:

ToolPath="C:\Program Files (x86)\Microsoft SDKs\Windows\v7.0A\Bin"

这解决了问题。

默认情况下,它似乎在以下位置运行新的 4.0 框架版本:C:\Program Files (x86)\Microsoft SDKs\Windows\v7.0A\Bin\NETFX 4.0 Tools

希望这对其他人有所帮助。

【讨论】:

  • 谢谢克雷格!这对我帮助很大!
  • 我在工程文件中设置如下:AutoC:\Program Files\Microsoft SDKs\Windows\v7.0\bin
  • 如果找不到 3.5 工具,MSBuild 将使用“NETFX 4.0 工具”中的 4.0 工具用于 3.5 项目。我的回答可能有助于解决问题的根本原因,避免需要在单个项目文件中解决问题。
  • 我试过这个,但我仍然无法让它工作。我发现这是因为我的项目在网络共享上。在我将它移到本地硬盘后,一切都运行良好。
【解决方案2】:

MSBuild 使用注册表获取 v3.5 工具的路径。如果无法识别 3.5 工具的路径,则需要 v3.5 SDK 工具的 MSBuild 任务将回退到 v4.0 路径 - 查看用于在 C:\Windows\Microsoft 中设置 TargetFrameworkSDKToolsDirectory 属性的逻辑。 NET\Framework\v4.0.30319\Microsoft.NETFramework.props,如果你真的感兴趣的话。

您可以按如下方式诊断和解决此问题:

安装Process Monitor并设置过滤器来监控msbuild对注册表的访问(事件类:注册表,进程名:msbuild.exe,所有类型的结果)。

运行您的构建。

搜索匹配“MSBuild\ToolsVersions\4.0\SDK35ToolsPath”的 RegQueryValue 访问的进程监视器。请注意,这可能位于“HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft”或“HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft”下。

如果您查看注册表中的此键,您会发现它为另一个注册表值设置别名,例如“$(注册表:HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Microsoft SDKs\Windows\v7.1\WinSDK-NetFx35Tools-x86@InstallationFolder)” 此后不久,您可能会看到“未找到名称”结果。如果您查看预期的密钥应该在哪里,您会发现它们与请求的密钥不匹配(缺少连字符并且可能没有以“-86”结尾的密钥)。

应该清楚您需要更正的内容。我选择导出不正确的密钥,编辑 .reg 文件并运行它以创建正确的密钥。

无效注册表项的一个原因可能是 Microsoft SDK v7.1 安装中的错误:

http://connect.microsoft.com/VisualStudio/feedback/details/594338/tfs-2010-build-agent-and-windows-7-1-sdk-targeting-net-3-5-generates-wrong-embedded-resources

【讨论】:

  • @DanMalcom 这是一个非常彻底的答案,但在我的情况下,可能还有这个用户案例,真正的问题不是将 ToolPath 设置为 $(TargetFrameworkSDKToolsDirectory)。如果您可以基于此编辑您的答案。我将在下面删除我的答案。
  • @Justin 如果您遇到我描述的注册表问题,那么 $(TargetFrameworkSDKToolsDirectory) 最终将不正确,例如针对 3.5 框架(v2.0 运行时)的构建的 4.0 工具(v4 运行时)。如果 SDK 工具安装正确,则不必将 $(ToolPath) 设置为 $(TargetFrameworkSDKToolsDirectory) 或硬编码路径。
  • 这在 3 年后的另一个项目中再次发生。很高兴我写了这篇文章!
  • 感谢您的调查。我在使用 node-gyp 为 Node.js 构建本机插件时遇到了同样的问题,并且在阅读您的回复后能够找到合适的解决方案。如果有人感兴趣,请在此处跟踪该问题:code.google.com/p/gyp/issues/detail?id=457
【解决方案3】:

我发现这是最简单的方法,它适用于:On GenerateSerializationAssemblies>

<SGenToolPath>C:\Program Files\Microsoft SDKs\Windows\v6.0A\bin</SGenToolPath>

【讨论】:

  • 对我们非常有用 - 在我看来,这更好,因为它允许您指定要使用的 sgen 版本 PER PROJECT。请注意,Visual Studio 没有此设置的 UI,如果您在 VS 中打开项目文件,它会将其显示为无效。但是,它确实有效。另一个提醒,为 BOTH RELEASE AND DEBUG 指定它!
【解决方案4】:

问题是 $(SGenToolPath) 不是由 MSBuild 设置的。如果您使用$(TargetFrameworkSDKToolsDirectory),那么它将尝试根据$(TargetFrameworkVersion) 解析路径。

使用标签进行 printf() 样式调试很有帮助。暂时添加以下内容。

<Target Name="AfterBuild" DependsOnTargets="AssignTargetPaths;Compile;ResolveKeySource" Inputs="$(MSBuildAllProjects);@(IntermediateAssembly)" Outputs="$(OutputPath)$(_SGenDllName)">
  <Message Text="SGenPath: $(SGenPath)" Importance="high"/>
  <Message Text="TargetFrameworkVersion: $(TargetFrameworkVersion)" Importance="high"/>
  <Message Text="TargetFrameworkSDKToolsDirectory : $(TargetFrameworkSDKToolsDirectory )" Importance="high"/>

【讨论】:

    【解决方案5】:

    @Craig - 您是否在构建机器上手动安装了 7.0A 框架。如果是这样,您的问题可能是您的注册表设置,而不是 msbuild。查看 LocalMachine -> Software -> Microsoft -> MSBuild -> ToolsVersions -> 4.0 -> SDK35ToolsPath 并确保此处引用的 reg 密钥有效。 (提示:确保 -x86 只有在 -x86 键存在时才存在。)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-11-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-10-27
      • 1970-01-01
      • 2017-04-30
      • 1970-01-01
      相关资源
      最近更新 更多