VS.NET 2010/MSBUILD可以为.NET 3.5 SP1生成XmlSerializers吗?

fli*_*ubt 12 msbuild sgen visual-studio-2010 .net-reflector xmlserializer

我刚刚将包含WinForms,通用库和Web应用程序的VS 2008解决方案升级到VS 2010,但所有项目仍然针对.NET 3.5 SP 1.我使用此技术为我的常用库生成XmlSerializers.WinForms应用程序运行正常.当我的Web应用程序尝试使用引用相同XmlSerializers的这些库运行时,它会抛出以下内容:

'/ WebSubscribers'应用程序中的服务器错误.无法加载文件或程序集"Ceoimage.Basecamp.XmlSerializers"或其依赖项之一.此程序集由比当前加载的运行时更新的运行时构建,无法加载.描述:执行当前Web请求期间发生未处理的异常.请查看堆栈跟踪以获取有关错误及其源自代码的位置的更多信息.

异常详细信息:System.BadImageFormatException:无法加载文件或程序集"Ceoimage.Basecamp.XmlSerializers"或其依赖项之一.此程序集由比当前加载的运行时更新的运行时构建,无法加载.

我已经使用.NET Reflector查看了XmlSerializer的引用,并看到它引用了2.0和4.0版本mscorlib以及3.5和4.0版本System.Data.Linq.奇怪的是,它只使用4.0版本System.Xml.那可能是我的问题.

如何使用这些XmlSerializers运行Web应用程序?当我简单地删除那些XmlSerializers时,Web应用程序运行正常.这是一个选项,但是如何强制MSBUILD为特定版本的CLR创建序列化程序?

这是我添加到项目文件的MSBuild任务,它强制创建XmlSerializers:

<Target Name="AfterBuild" DependsOnTargets="AssignTargetPaths;Compile;ResolveKeySource" Inputs="$(MSBuildAllProjects);@(IntermediateAssembly)" Outputs="$(OutputPath)$(_SGenDllName)">
 <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>
Run Code Online (Sandbox Code Playgroud)

Dan*_*olm 8

MSBuild 4将(应该......)使用3.5工具来构建3.5个项目.但是,看起来它无法解决3.5工具的位置并使用4.0工具.结果是它正在构建您的3.5项目(使用CLR 2.0.50727程序集),但4.0 sgen.exe工具正在生成Ceoimage.Basecamp.XmlSerializers.dll作为CLR 4.0.30319程序集.

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,所有类型的结果)

运行你的构建

搜索Process Monitor以获得与"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)"在此之后不久,您可能会看到"NAME NOT FOUND"结果,因为msbuild尝试从指定的密钥加载值.

应该清楚从这里添加/修改哪些键.

注册表值错误有几个可能的原因.在我的情况下,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-资源


fli*_*ubt 2

我发现我可以显式指定 SGEN 任务的工具路径来使用 3.5 版本,如下所示:

<SGen BuildAssemblyName="$(TargetFileName)" BuildAssemblyPath="$(OutputPath)" References="@(ReferencePath)" ShouldGenerateSerializer="true" UseProxyTypes="false" KeyContainer="$(KeyContainerName)" KeyFile="$(KeyOriginatorFile)" DelaySign="$(DelaySign)" ToolPath="C:\Program Files\Microsoft SDKs\Windows\v7.0A\bin">
Run Code Online (Sandbox Code Playgroud)