Как выбрать другой app.config для нескольких конфигураций сборки

У меня есть проект dll-типа, который содержит тесты интеграции MSTest. На моей машине тесты проходят, и я хочу, чтобы то же самое происходило на сервере CI (я использую TeamCity). Но тесты терпят неудачу, потому что мне нужно настроить некоторые параметры в app.config. Вот почему я думал иметь отдельный второй файл app.config, который будет содержать настройки для сервера CI.

Итак, я хотел бы иметь

/Sln
 /Proj
  app.config (I think this is required by VS)
  app.Release.config (This is a standalone independent config file)

Таким образом, если я выберу конфигурацию Release в конфигурации сборки в CI, я бы хотел использовать файл app.Release.config вместо app.config

Проблема
Это не похоже на простые проекты типа .dll. Для веб-проектов я могу делать преобразования веб-конфигурации. Я нашел хак, как сделать эти преобразования для проекта типа dll, но я не большой поклонник хаков.

Вопрос
Что такое стандартный подход к настройке файлов app.config в зависимости от конфигурации сборки для проектов .NET(таких как Debug, Release,...)?

Ответ 1

Используйте плагин SlowCheetah. Для получения дополнительных опций и подробностей о том, как использовать SlowCheetah, продолжайте читать.

Как вы уже заметили, нет никакого стандартного и простого способа использования разных конфигурационных файлов для проекта типа библиотеки (DLL). Причина в том, что нынешнее мышление: "Вам не нужно"! Разработчики рамок считают, что вам нужна конфигурация для исполняемого файла: будь то консоль, рабочий стол, веб-приложение, мобильное приложение или что-то еще. Если вы начнете предоставлять конфигурацию для dll, вы можете получить что-то, что я могу назвать конфигурационным адом. Вы можете больше не понимать (легко), почему эта и эти переменные имеют такие странные ценности, которые кажутся из ниоткуда.

"Держись", - можешь сказать, - но мне это нужно для интеграции/модульного тестирования, и это библиотека! ". И это правда, и это то, что вы можете сделать (выберите только один, не смешивайте):

1. SlowCheetah - преобразует текущий файл конфигурации

Вы можете установить SlowCheetah - подключаемый модуль Visual Studio, который выполняет все ваши низкоуровневые XML-трюки (или преобразования). Как это работает, кратко:

  • Установите SlowCheetah и перезапустите Visual Studio (Visual Studio > Инструменты > Расширения и обновления... > Интернет > Галерея Visual Studio > найдите "Медленный гепард" )
  • Определите свои конфигурации решений (по умолчанию есть Debug и Release), вы можете добавить больше (щелкните правой кнопкой мыши по решению в обозревателе решений > Configuration Manager... > Конфигурация Active Solution > Создать...
  • При необходимости добавьте файл конфигурации
  • Щелкните правой кнопкой мыши файл конфигурации > Добавить преобразование
    • Это создаст файлы Transformation - по одному для вашей конфигурации
    • Преобразование файлов работает как инжекторы/мутаторы, они находят необходимый XML-код в исходном файле конфигурации и вводят новые строки или изменяют необходимое значение, что бы вы ни говорили вам сделать

2. Скрипт с .proj файлом - копирует-переименовывает весь новый файл конфигурации

Первоначально взято из здесь. Это настраиваемая задача MSBuild, которую вы можете встроить в файл .proj Visual Studio. Скопируйте и вставьте следующий код в файл проекта

<Target Name="AfterBuild">
    <Delete Files="$(TargetDir)$(TargetFileName).config" />
    <Copy SourceFiles="$(ProjectDir)\Config\App.$(Configuration).config"
          DestinationFiles="$(TargetDir)$(TargetFileName).config" />
</Target>

Теперь создайте папку в проекте под названием Config и добавьте туда новые файлы: App.Debug.config, App.Release.config и т.д. Теперь, в зависимости от вашей конфигурации, Visual Studio выберет конфигурационный файл из папки Config и скопирует его в каталог вывода. Поэтому, если у вас есть проект PatternPA.Test.Integration и выбранная конфигурация Debug, в выходной папке после сборки вы найдете файл PatternPA.Test.Integration.dll.config, который был скопирован из Config\App.Debug.config и впоследствии переименован.

Вот некоторые заметки, которые вы можете оставить в конфигурационных файлах

<?xml version="1.0" encoding="utf-8"?>
<configuration>

    <!-- This file is copied and renamed by the 'AfterBuild' MSBuild task -->

    <!-- Depending on the configuration the content of projectName.dll.config 
        is fully substituted by the correspondent to build configuration file 
        from the 'Config' directory. -->

</configuration>

В Visual Studio вы можете иметь что-то вроде этого

Project structure

3. Использовать скриптовые файлы вне Visual Studio

Каждый инструмент построения (например NAnt, MSBuild) предоставит возможности для преобразования конфигурационного файла в зависимости от конфигурации. Это полезно, если вы строите свое решение на машине сборки, где вам нужно больше контролировать, что и как подготовить продукт к выпуску.

Например, вы можете использовать задачу веб-публикации dll для преобразования любого файла конфигурации

<UsingTask AssemblyFile="..\tools\build\Microsoft.Web.Publishing.Tasks.dll"
    TaskName="TransformXml"/>

<PropertyGroup>
    <!-- Path to input config file -->  
    <TransformInputFile>path to app.config</TransformInputFile>
    <!-- Path to the transformation file -->    
    <TransformFile>path to app.$(Configuration).config</TransformFile>
    <!-- Path to outptu web config file --> 
    <TransformOutputFile>path to output project.dll.config</TransformOutputFile>
</PropertyGroup>

<Target Name="transform">
    <TransformXml Source="$(TransformInputFile)"
                  Transform="$(TransformFile)"
                  Destination="$(TransformOutputFile)" />
</Target>

Ответ 2

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

  • Щелкните правой кнопкой мыши проект в обозревателе решений и выберите Выгрузить проект.
  • Проект будет выгружен. Щелкните правой кнопкой мыши проект еще раз и выберите Изменить <YourProjectName> .cproj.
  • Теперь вы можете редактировать файл проекта внутри Visual Studio.
  • Найдите место в файле *.csproj, в который включен ваш файл конфигурации приложения. Он будет выглядеть следующим образом:
    <ItemGroup>
        <None Include="App.config"/>
    </ItemGroup>
  • Замените следующие строки:
    <ItemGroup Condition=" '$(Configuration)' == 'Debug' ">
        <None Include="App.Debug.config"/>
    </ItemGroup>

    <ItemGroup Condition=" '$(Configuration)' == 'Release' ">
        <None Include="App.Release.config"/>
    </ItemGroup>

Я не пробовал этот подход к файлам app.config, но он отлично работал с другими элементами проектов Visual Studio. Вы можете настроить процесс сборки практически любым способом. В любом случае, дайте мне знать результат.

Ответ 3

Вы должны рассмотреть ConfigGen. Он был разработан для этой цели. Он создает файл конфигурации для каждой машины развертывания на основе файла шаблона и файла настроек. Я знаю, что это не отвечает на ваш вопрос конкретно, но это может хорошо ответить на вашу проблему.

Чтобы вместо Debug, Release и т.д. у вас могли быть Test, UAT, Production и т.д. У вас также могут быть разные настройки для каждой машины для разработчиков, так что вы можете создать конфигурацию, специфичную для вашей машины dev, и изменить ее, не затрагивая никаких еще одно развертывание.

Пример использования может быть...

<Target Name="BeforeBuild">
    <Exec Command="C:\Tools\cfg -s $(ProjectDir)App.Config.Settings.xls -t       
        $(ProjectDir)App.config.template.xml -o $(SolutionDir)ConfigGen" />

    <Exec Command="C:\Tools\cfg -s $(ProjectDir)App.Config.Settings.xls -t
        $(ProjectDir)App.config.template.xml -l -n $(ProjectDir)App.config" />
</Target>

Если вы поместите это в свой файл .csproj, и у вас есть следующие файлы...

$(ProjectDir)App.Config.Settings.xls

MachineName        ConfigFilePath   SQLServer        

default             App.config      DEVSQL005
Test                App.config      TESTSQL005
UAT                 App.config      UATSQL005
Production          App.config      PRODSQL005
YourLocalMachine    App.config      ./SQLEXPRESS


$(ProjectDir)App.config.template.xml 

<?xml version="1.0" encoding="utf-8" standalone="yes"?>
   <configuration>
   <appSettings>
       <add key="ConnectionString" value="Data Source=[%SQLServer%]; 
           Database=DatabaseName; Trusted_Connection=True"/>
   </appSettings>
</configuration>

... тогда это будет результат...

Из первой команды создается файл конфигурации, созданный для каждой среды, указанной в файле xls, помещенный в выходной каталог $(SolutionDir) ConfigGen

.../solutiondir/ConfigGen/Production/App.config

<?xml version="1.0" encoding="utf-8" standalone="yes"?>
   <configuration>
   <appSettings>
       <add key="ConnectionString" value="Data Source=PRODSQL005; 
           Database=DatabaseName; Trusted_Connection=True"/>
   </appSettings>
</configuration>

Из второй команды локальный файл App.config, используемый на вашем компьютере-разработчике, будет заменен на сгенерированную конфигурацию, указанную локальным (-l) коммутатором и именем файла (-n).

Ответ 4

Используя тот же подход, что и Romeo, я адаптировал его к Visual Studio 2010:

 <None Condition=" '$(Configuration)' == 'Debug' " Include="appDebug\App.config" />

 <None Condition=" '$(Configuration)' == 'Release' " Include="appRelease\App.config" />

Здесь вам нужно хранить файлы App.config в разных каталогах (appDebug и appRelease). Я тестировал его, и он отлично работает!

Ответ 5

Я использую инструмент XmlPreprocess для манипулирования конфигурационными файлами. Он использует один файл сопоставления для нескольких сред (или нескольких целей сборки в вашем случае). Вы можете редактировать файл сопоставления Excel. Он очень прост в использовании.

Ответ 6

SlowCheetah и FastKoala из галереи VisualStudio - это очень хорошие инструменты, которые помогают справиться с этой проблемой.

Однако, если вы хотите избежать добавления или использовать принципы, которые они реализуют более широко во всех ваших процессах сборки/интеграции, добавление этого в ваши файлы msbuild * proj является сокращенным исправлением.

Примечание: это более или менее передел № 2 ответа @oleksii.

Это работает для проектов.exe и.dll:

  <Target Name="TransformOnBuild" BeforeTargets="PrepareForBuild">
    <TransformXml Source="App_Config\app.Base.config" Transform="App_Config\app.$(Configuration).config" Destination="app.config" />
  </Target>

Это работает для веб-проектов:

  <Target Name="TransformOnBuild" BeforeTargets="PrepareForBuild">
    <TransformXml Source="App_Config\Web.Base.config" Transform="App_Config\Web.$(Configuration).config" Destination="Web.config" />
  </Target>

Обратите внимание, что этот шаг происходит еще до начала сборки. Преобразование конфигурационного файла происходит в папке проекта. Так что преобразованный web.config доступен, когда вы отлаживаете (недостаток SlowCheetah).

Помните, что если вы создаете папку App_Config (или что бы вы ни выбрали для ее вызова), различные промежуточные файлы конфигурации должны иметь Build Action = None и Copy to Output Directory = Не копировать.

Это объединяет оба варианта в один блок. Соответствующий выполняется на основе условий. Задача TransformXml определяется сначала:

<Project>
<UsingTask TaskName="TransformXml" AssemblyFile="$(MSBuildExtensionsPath)\Microsoft\VisualStudio\v$(VisualStudioVersion)\Web\Microsoft.Web.Publishing.Tasks.dll" />
<Target Name="TransformOnBuild" BeforeTargets="PrepareForBuild">
    <TransformXml Condition="Exists('App_Config\app.Base.config')" Source="App_Config\app.Base.config" Transform="App_Config\app.$(Configuration).config" Destination="app.config" />
    <TransformXml Condition="Exists('App_Config\Web.Base.config')" Source="App_Config\Web.Base.config" Transform="App_Config\Web.$(Configuration).config" Destination="Web.config" />
</Target>

Ответ 7

Посмотрите, поможет ли вам механизм преобразования XDT (web.config). В настоящее время он поддерживается только для веб-проектов, но технически нет ничего, что помешало бы вам использовать его в других типах приложений. Есть много руководств о том, как использовать XDT, вручную редактируя файлы проекта, но я нашел плагин, который отлично работает: https://visualstudiogallery.msdn.microsoft.com/579d3a78-3bdd-497c-bc21-aa6e6abbc859

Плагин только помогает настроить конфигурацию, ее не нужно строить, и решение может быть создано на других машинах или на сервере сборки без плагина или любых других необходимых инструментов.

Ответ 8

После некоторых исследований по управлению конфигурациями для разработки и сборки и т.д., я решил опрокинуть свой собственный, я сделал его доступным на битбакете по адресу: https://bitbucket.org/brightertools/contemplate/wiki/Home

Это несколько файлов конфигурации для нескольких сред, это базовый инструмент замены записи конфигурации, который будет работать с любым текстовым файлом.

Надеюсь, что это поможет.

Ответ 9

Я решил эту тему с решением, которое я нашел здесь: http://www.blackwasp.co.uk/SwitchConfig.aspx

Короче говоря, они заявляют: "добавив событие post-build. [...] Нам нужно добавить следующее:

if "Debug"=="$(ConfigurationName)" goto :nocopy
del "$(TargetPath).config"
copy "$(ProjectDir)\Release.config" "$(TargetPath).config"
:nocopy

Ответ 10

Я слышал хорошие вещи о SlowCheetah, но не смог заставить его работать. Я сделал следующее: добавьте тег am к каждому для определенной конфигурации.

Пример:

<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'UAT|AnyCPU'">
    <OutputPath>bin\UAT\</OutputPath>
    <PlatformTarget>AnyCPU</PlatformTarget>
    <DebugType>pdbonly</DebugType>
    <Optimize>true</Optimize>
    <DefineConstants>TRACE</DefineConstants>
    <ErrorReport>prompt</ErrorReport>
    <WarningLevel>4</WarningLevel>
    <AppConfig>App.UAT.config</AppConfig>
  </PropertyGroup>