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

115

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

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

/ Sln
 / Рго
  app.config (я думаю, этого требует VS)
  app.Release.config (это автономный независимый файл конфигурации)

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

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

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

алексей
источник

Ответы:

154

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

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

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

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

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

  • Установите SlowCheetah и перезапустите Visual Studio (Visual Studio> Инструменты> Расширения и обновления ...> В сети> Галерея Visual Studio> найдите "Slow Cheetah")
  • Определите конфигурации своего решения ( отладка и выпуск по умолчанию), вы можете добавить больше (щелкните правой кнопкой мыши решение в обозревателе решений > Configuration Manager ... > Active Solution Configuration > New ...
  • При необходимости добавьте файл конфигурации
  • Щелкните правой кнопкой мыши файл конфигурации> Добавить преобразование
    • Это создаст файлы преобразования - по одному для вашей конфигурации.
    • Файлы преобразования работают как инжекторы / мутаторы, они находят необходимый 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 у вас может быть что-то вроде этого

Структура проекта

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>
алексей
источник
Ваше второе решение работает нормально, но не для публикации веб-проектов. После публикации проекта ASP.NET публикуется исходный файл web.config.
Massood Khaari
3
@MassoodKhaari, вам нужно убедиться, что эта задача вызывается для цели публикации. Когда вы публикуете проект, вызывается отдельная цель сборки, которая может не вызывать AfterBuildцель по умолчанию . Во время типичной компиляции AfterBuildцель вызывается по умолчанию. В случае публикации должно быть быстрое исправление
Алексей
1
Использовал ваш второй метод (вроде). Пошел в свойствах проекта и редактировали BeforeBuild , чтобы скопировать App.<Target>.configнад App.configв директории проекта , а не выход реж.
SparK
@oleksii Вы правы. Но я все еще не мог найти цель, которую использует мой процесс веб-публикации (в Visual Studio 2013).
Massood Khaari
1
Я использую второй метод, но мне нужно добавить условие в цель AfterBuild, чтобы убедиться, что файл действительно существует перед удалением. У меня есть конфигурация сборки Debug, которая в основном просто использует файл App.config по умолчанию, но у меня не было App.Debug.config, что означало, что этап сборки завершится ошибкой. Я только что добавил Condition="Exists('$(ProjectDir)App.$(Configuration).config')".
Siewers
23

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

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

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

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

vharavy
источник
Tnx за ответ, но это не работает с app.config. VS требует обязательного использования app.configи не применяет конфигурацию выпуска, если я использую сборку VS или средство запуска сборки Teamcity VS sln.
oleksii
2
Здесь объясняется, как это сделать: Включить app.debug.config app.release.config
Габриэлизало
1
Почему за этот ответ так много голосов? Я попробовал, но не работает. Фактически, как в режиме отладки, так и в режиме выпуска нет файла App.config и, следовательно, нет соответствующего файла в выходной папке. Файлы App.Debug.config и App.Release.config не имеют никакого значения для Visual Studio.
MarkusParker
Это не работает: .csproj не открывается, сообщение об ошибке «элементы вне целевых элементов должны иметь: Include, Update или Remove»
Эло,
12

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

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

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

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

Дэниел Дайсон
источник
2
Спасибо за ответ, выглядит неплохо. Но есть и недостатки, он показывает только 75 загрузок (таким образом, он незрелый) и работает только с .xls или .xlsx. Я действительно не хочу полагаться на еще один пользовательский формат документа для простых операций. Я искал более стандартный подход ...
Алексей
2
Справедливо, хотя в нем говорится, что на CodePlex было загружено 194 загрузки, xls - это электронная таблица, вряд ли пользовательский формат, и я знаю три крупных инвестиционных банка, которые одобрили это для использования, поэтому, если он достаточно хорош для них ... Кроме того, один из запрошенных в настоящее время функций является использование xml для настроек. Он почти готов, но я все равно предпочитаю использовать электронную таблицу. Намного проще увидеть каждую настройку для каждой среды в табличном виде,
Дэниел Дайсон
Сейчас мы находимся на завершающей стадии тестирования версии configGen, которую можно использовать для создания текстовых файлов, а не только xml. Поэтому, если вы хотите сгенерировать css, sql, javascript и т. Д. Для конкретной среды, следите за сайтом configGen
Дэниел Дайсон,
Спасибо Даниилу за решение, это именно то, что я искал. Я дам ему попробовать.
Бхупиндер Сингх
10

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

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

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

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

Тем Перу
источник
3

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

Ludwo
источник
3

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

Однако, если вы хотите избежать надстроек или использовать принципы, которые они реализуют более широко во всех процессах сборки / интеграции, тогда добавление этого в ваши файлы 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 = Do not copy.

Это объединяет оба варианта в один блок. Соответствующий выполняется исходя из условий. Однако сначала определяется задача 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>

Eniola
источник
Я просто попробовал это в Visual Studio 2017, и это не работает. Shoot. Я очень надеялся, что это сработает, потому что похоже, что это проще всего реализовать.
Грег Бургхардт
Задача TransformXml не определена в примерах. Я добавляю запись. Вы можете определить его в файле mycustom.targets, который будет включен во все ваши проекты запуска в вашем решении.
Эниола
@GregBurghardt, хочешь попробовать сейчас?
Эниола
Я мог бы попробовать. Я установил плагин Config Transform для Visual Studio, и он отлично сработал. Мне действительно интересно, действительно ли плагин делает то, что делает ваш ответ.
Грег Бургхардт
Хорошо, дайте мне знать, как это происходит.
Эниола
1

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

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

TGasdf
источник
Это должен быть ответ сейчас. Просто опробовал его на VS 2017, и он работает как шарм. Публикация проекта не требуется. Просто построи это. Отлично подходит для нашего тестового проекта для использования в нашей сборке с непрерывной интеграцией, поэтому мы можем запускать тесты Selenium в автономном режиме, но локально они запускаются при открытии браузера. +1,000,000, если бы я мог.
Грег Бургхардт
1

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

Вкратце то, что они заявляют: «путем добавления события после сборки. [...] Нам нужно добавить следующее:

if "Debug"=="$(ConfigurationName)" goto :nocopy
del "$(TargetPath).config"
copy "$(ProjectDir)\Release.config" "$(TargetPath).config"
:nocopy
Janbro
источник
Безусловно, это самый простой способ сделать то, что должно было быть очень простой и важной функцией, которую облажали сверхмудрые! Спасибо, Янбро.
BoiseBaked
1

Я слышал хорошие отзывы о 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>
Майк
источник
Это похоже на еще один очень простой способ изменить файлы app.config в соответствии с конфигурацией сборки. Майк, вы тестировали стандартные конфигурации отладки и выпуска?
BoiseBaked
0

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

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

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

Марк Редман
источник