11

Я только что обновил VS 2008 решение, содержащее WinForms, общие библиотеки использования и веб-приложение для VS 2010, но все проекты по-прежнему нацелены на .NET 3.5 SP 1. Я использую this technique для генерации XmlSerializers для моих общих библиотек. Приложение WinForms работает нормально. Когда мой веб-приложение пытается выполнить с помощью этих библиотек, которые ссылаются на одни и те же XmlSerializers, он выдает следующее:Может ли VS.NET 2010/MSBUILD создавать XmlSerializers для .NET 3.5 SP1?

Ошибка сервера в приложение '/ WebSubscribers. Не удалось загрузить файл или сборка 'Ceoimage.Basecamp.XmlSerializers' или одна из его зависимостей. Эта сборка построена во время выполнения, но не более , загруженной в настоящее время, и не может быть загружена . Описание: Необработанное исключение произошло во время выполнения текущего веб-запроса . Просмотрите трассу стека для получения дополнительной информации информацию об ошибке и по которой это код генерации кода.

Сведения об исключении: System.BadImageFormatException: Не удалось загрузить файл или сборку «Ceoimage.Basecamp.XmlSerializers» или одну из его зависимостей. Эта сборка построена с использованием среды выполнения, более новой, чем текущая загруженная среда выполнения и не может быть загружена.

Я посмотрел на ссылки на XMLSerializer, используя .NET Reflector и посмотреть, она ссылается как на версии mscorlib 2.0 и 4.0, а также 3.5 и 4.0 версии System.Data.Linq. Как ни странно, он использует только 4.0 версию System.Xml. Вероятно, это проблема.

Как я могу запустить веб-приложение с помощью этих XmlSerializers? Когда я просто удаляю эти XmlSerializers, веб-приложение работает нормально. Это вариант, но как заставить 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> 
+1

следует добавить, что изменить в ответ, поэтому мы может проголосовать за это, это, кажется, лучшее решение :) – Lucas

ответ

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"> 
+0

Вы меняете файл целей или вы каким-то образом модифицируете свои файлы проектов? Я не знаю, как применить это к моей среде ... –

+0

Это было давно, но я уверен, что я отредактировал файл CSPROJ напрямую. – flipdoubt

2

ARE YOU зависит от что-нибудь 4.0 конкретного?

Если вы вызываете MSBuild 4.0, вы получите 4.0 инструмента. Если вы вызовете MSBuild 3.5, вы получите 3.5 инструментария (это то, что вы хотите, поскольку вы явно размещаете в 2.0 CLR).

Другой вариант - разместить 4.0 CLR на вашем веб-сервере. Если это не открыто, в вашем потоке не должно быть никаких целевых объектов размером 4.0.

+0

Я только что проверил один из моих проектов и нашел в нем только ссылки 2.0 и 3.5 сборки фреймов. Однако одна вещь, которую я замечаю, заключается в том, что свойство «Специфическая версия» каждой структуры ссылается на «false». Когда я выгружаю проект и заглядываю в файл .CSPROJ, в теге свойств упоминаются такие инструменты 4.0: '' Когда я изменяю 'ToolsVersion' на' 3.5', VS 2010 преобразует проект и возвращает значение '4.0'. – flipdoubt

+0

@flipdoubt: VS2010 forcing 4.0 toolsversion - известная проблема (есть поиск). проблема здесь в том, что импортируемая задача SGen - это задача 4.0 sgen, которая по умолчанию будет равна 4.0 SGen.exe. Возможно, переопределить ToolPath для работы 3.5 SGen mioght. –

+0

А потом я посмотрел на ваше редактирование. Я думаю, что это лучшее исправление, учитывая, что запуск ваших проектов ToolsVersion 4.0 через MSBuild 3.5 не будет долгосрочным решением. –

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. Задачи MSBuild, требующие инструментов SDK версии 3.5, возвращаются к пути v4.0, если путь к 3.5 инструментов не могут быть идентифицированы - посмотрите на логику, используемую для установки свойства TargetFrameworkSDKToolsDirectory в C: \ Windows \ Microsoft.NET \ Framework \ v4.0.30319 \ Microsoft.NETFramework.props, если вы действительно заинтересованы.

Вы можете диагностировать и устранить возможные проблемы реестра следующим образом:

Установить Process Monitor и настроить фильтр для контроля доступа к реестру с помощью MSBuild (класс событий: реестр, Имя процесса: MSBuild.exe, все типы результата)

запустить свой билд

Search Process Monitor для RegQueryValue сопоставления доступа "MSBuild \ ToolsVersions \ 4.0 \ SDK35ToolsPath". Обратите внимание, что это может быть как «HKEY_LOCAL_MACHINE \ SOFTWARE \ Microsoft», так и «HKEY_LOCAL_MACHINE \ SOFTWARE \ Wow6432Node \ Microsoft»

Если у вас есть этот ключ в реестре, вы увидите, что он псевдонимы другого реестра значение, например «$ (Реестр: HKEY_LOCAL_MACHINE \ SOFTWARE \ Microsoft \ Microsoft SDK \ Windows \ v7.1 \ WinSDK-NetFx35Tools-x86 @ InstallationFolder)" Вскоре после этого вы, вероятно, увидите результат "NAME NOT FOUND", так как msbuild пытается загрузите значение из указанного ключа.

Должно быть ясно, какие ключи вам нужно добавить/исправить отсюда.

Существует несколько возможных причин неправильного значения реестра. В моем случае проблема с установкой v7.1 Microsoft SDK означает, что ключи реестра были названы неправильно, который был идентифицирован как ошибка здесь:

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

+0

+1 для объяснения –

+0

Спасибо за этот ответ. Я совмещаю это с http://stackoverflow.com/a/2739132/281084, чтобы решить мою проблему –