Может ли VS.NET 2010 / MSBUILD создавать XmlSerializer для .NET 3.5 SP1? - PullRequest
11 голосов
/ 23 августа 2010

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

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

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

Я просмотрел ссылки на XmlSerializer с использованием .NET Reflector и увидел, что он ссылается как на версии 2.0 и 4.0 mscorlib, так и на версии 3.5 и 4.0 System.Data.Linq. Странно, он использует только версию 4.0 System.Xml. Это, наверное, моя проблема прямо здесь.

Как заставить веб-приложение работать с использованием этих XmlSerializer? Когда я просто удаляю эти XmlSerializer, веб-приложение работает нормально. Это вариант, но как я могу заставить MSBUILD создавать сериализаторы для определенной версии CLR?

Вот задача MSBuild, которую я добавляю в файлы проекта, которая вызывает создание XmlSerializer:

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

Ответы [ 3 ]

8 голосов
/ 18 апреля 2011

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 (Класс события: Registry, Имя процесса: msbuild.exe,все типы результатов)

Запустите сборку

Монитор процесса поиска для доступа RegQueryValue, совпадающего с "MSBuild \ ToolsVersions \ 4.0 \ SDK35ToolsPath".Обратите внимание, что это может быть либо "HKEY_LOCAL_MACHINE \ SOFTWARE \ Microsoft", либо "HKEY_LOCAL_MACHINE \ SOFTWARE \ Wow6432Node \ Microsoft"

Если вы посмотрите на этот ключ в реестре, вы увидите, что это псевдонимыдругое значение реестра, например "$ (Registry: HKEY_LOCAL_MACHINE \ SOFTWARE \ Microsoft \ Microsoft SDKs \ Windows \ v7.1 \ WinSDK-NetFx35Tools-x86 @ InstallationFolder)" Вскоре после этого вы, вероятно, увидите результат "ИМЯ НЕ НАЙДЕНО"поскольку 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-resources

2 голосов
/ 25 августа 2010

Я обнаружил, что могу явно указать путь к инструментам задачи 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">
2 голосов
/ 24 августа 2010

Вы полагаетесь на что-нибудь конкретное 4.0?

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

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

...