views:

103

answers:

2

I just upgraded a VS 2008 solution containing WinForms, general use libraries, and a web app to VS 2010, but all projects still target .NET 3.5 SP 1. I use this technique to generate XmlSerializers for my general use libraries. The WinForms app runs fine. When my web app tries to run using these libraries that reference the same XmlSerializers, it throws the following:

Server Error in '/WebSubscribers' Application. Could not load file or assembly 'Ceoimage.Basecamp.XmlSerializers' or one of its dependencies. This assembly is built by a runtime newer than the currently loaded runtime and cannot be loaded. Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.

Exception Details: System.BadImageFormatException: Could not load file or assembly 'Ceoimage.Basecamp.XmlSerializers' or one of its dependencies. This assembly is built by a runtime newer than the currently loaded runtime and cannot be loaded.

I have looked at the XmlSerializer's references using .NET Reflector and see it references both the 2.0 and 4.0 versions of mscorlib as well as the 3.5 and 4.0 versions of System.Data.Linq. Strangely, it only uses the 4.0 version of System.Xml. That is probably my problem right there.

How can I get the web app to run using these XmlSerializers? When I simply delete those XmlSerializers, the web app runs fine. This is an option, but how can I force MSBUILD to create serializers for a specific version of the CLR?

Here is the MSBuild task I add to project files that forces the creation of the 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>
+2  A: 

Are you reliant on anything 4.0 specific?

If you invoke MSBuild 4.0, you'll get 4.0 tools. If you invoke MSBuild 3.5, you'll get 3.5 tools (which is what you want as you're clearly hosting in a 2.0 CLR).

The other option is to put the 4.0 CLR on your web server. If that's not open, you shouldnt have any 4.0 targetted stuff in your stream.

Ruben Bartelink
I just checked one of my projects and found it only references 2.0 and 3.5 framework assemblies. One thing I notice, however, is that the `Specific Version` property of each framework references to `false`. When I unload a project and peek into the .CSPROJ file, the property tag does mention the 4.0 tools like so:`<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="4.0">`When I change the `ToolsVersion` to `3.5`, VS 2010 converts the project and returns the value to `4.0`.
flipdoubt
@flipdoubt: The VS2010 forcing 4.0 toolsversion is a known issue (have a search). the problem here is the SGen task being imported is the 4.0 sgen task which will default to the 4.0 SGen.exe Perhaps putting a ToolPath override to the 3.5 SGen mioght work.
Ruben Bartelink
And then I looked at your edit. I think that's the best fix given that running your ToolsVersion 4.0 projects through MSBuild 3.5 isnt going to be a long term solution
Ruben Bartelink
I guess you're just going to have to drop your accept rate percentage though - it's a bug in the MSBuild tooling that you can mark an assembly for 3.5 only to be blindsided by SGen not following through. Perhaps the best way to get an official answer on this is via the MS forums and/or Connect
Ruben Bartelink
A: 

I found I can explicitly specify the SGEN task's tools path to use the 3.5 version, like so:

<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">
flipdoubt