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

#.net #visual-studio #configuration #continuous-integration #release-management

#.net #visual-studio #конфигурация #непрерывная интеграция #управление выпуском

Вопрос:

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

Поэтому я хотел бы иметь

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

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

Проблема
Это не кажется простым для simple .проекты типа 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… > Конфигурация активного решения > Новый …
  • При необходимости добавьте файл конфигурации
  • Щелкните правой кнопкой мыши файл конфигурации > Добавить преобразование
    • Это создаст файлы преобразования — по одному для вашей конфигурации
    • Файлы преобразования работают как инжекторы / мутаторы, они находят необходимый XML-код в исходном файле конфигурации и вводят новые строки или изменяют необходимое значение, что бы вы ни сказали ему делать

2. Поработайте с файлом .proj — скопируйте-переименуйте совершенно новый файл конфигурации

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

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

Теперь создайте папку в проекте под названием Config и добавьте туда новые файлы: App.Debug.config, App.Release.config и так далее. Теперь, в зависимости от вашей конфигурации, Visual Studio выберет файл конфигурации из Config папки и скопирует-переименует его в выходной каталог. Итак, если у вас был PatternPA.Test.Выбран проект интеграции и конфигурация отладки, в папке вывода после сборки вы найдете PatternPA.Test. Файл Integration.dll.config, который был скопирован из ConfigApp.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) предоставит возможности для преобразования файла конфигурации в зависимости от конфигурации. Это полезно, если вы создаете свое решение на компьютере сборки, где вам нужно иметь больше контроля над тем, что и как вы готовите продукт к выпуску.

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

 <UsingTask AssemblyFile="..toolsbuildMicrosoft.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>
  

Комментарии:

1. Ваше второе решение работает нормально, но не для публикации веб-проектов. После публикации ASP.NET проект, исходный web.config опубликован.

2. @MassoodKhaari вам нужно убедиться, что эта задача вызывается для цели публикации. При публикации проекта вызывается отдельная цель сборки, которая может не вызывать цель по умолчанию AfterBuild . Во время обычной компиляции по умолчанию вызывается AfterBuild цель. Должно быть быстрое исправление для случая публикации

3. Использовал ваш второй метод (своего рода). Зашел в свойства проекта и отредактировал BeforeBuild , чтобы скопировать App.<Target>.config поверх App.config в каталог проекта , а не в каталог вывода.

4. @oleksii Ты прав. Но я все еще не мог найти цель, которую использует мой процесс веб-публикации (в Visual Studio 2013).

5. Я использую второй метод, но мне нужно добавить условие к цели AfterBuild, чтобы убедиться, что файл действительно существует, перед удалением. У меня есть конфигурация сборки Debug, которая в основном использует файл App.config по умолчанию, но у меня не было App.Debug.config, что означало, что этап сборки завершится неудачей. Я только что добавил Condition="Exists('$(ProjectDir)App.$(Configuration).config')" .

Ответ №2:

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

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

 <Условие ItemGroup=" '$(Configuration)' == 'Release' ">
 <Нет Include="App.Release.config"/>
 </ItemGroup>

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

Комментарии:

1. Спасибо за ответ, но это не работает с app.config. VS требует обязательного app.config и не применяет конфигурацию выпуска, если я использую VS build или Teamcity VS sln build runner.

2. Здесь объясняется, как это сделать: Включить app.debug.config app.release.config

3. Почему за этот ответ так много голосов «за»? Я попробовал, и это не сработало. На самом деле как в режиме отладки, так и в режиме выпуска нет файла App.config и, следовательно, нет соответствующего файла в выходной папке. Файлы App.Debug.config и App.Release.config не имеют никакого значения для Visual Studio.

4. Это не работает: .csproj не может быть открыт, сообщение об ошибке «элементы вне целевых элементов должны иметь: Включить, обновить или удалить»

Ответ №3:

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

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

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

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

Ответ №4:

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

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

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

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

    <Exec Command="C:Toolscfg -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, используемый на вашем компьютере разработчика, будет заменен сгенерированным config, указанным переключателем local (-l) и переключателем filename (-n).

Комментарии:

1. Tnx для ответа, это выглядит неплохо. Но есть некоторые недостатки, он показывает только 75 загрузок (таким образом, он не является зрелым) и работает только с .xls или .xlsx. Я действительно не хочу зависеть от еще одного пользовательского формата документа для простых операций. Я искал более стандартный подход…

2. Справедливое замечание, хотя в CodePlex указано 194 загрузки, xls — это электронная таблица, вряд ли пользовательский формат, и я знаю три крупных инвестиционных банка, которые одобрили это для использования, так что, если для них это достаточно хорошо… Кроме того, одна из запрашиваемых в настоящее время функций — использовать xml для настроек. Он почти готов, но я все равно предпочитаю подход с использованием электронных таблиц. Гораздо проще просмотреть все настройки для каждой среды в табличном виде

3. Сейчас мы находимся на завершающей стадии тестирования версии ConfigGen, которая может использоваться для генерации обычных текстовых файлов, а не только xml. Итак, если вы хотите сгенерировать css, sql, javascript и т.д. для конкретной среды, следите за сайтом ConfigGen

4. спасибо Дэниелу за решение, это именно то, что я искал. Я попробую.

Ответ №5:

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

Пример:

 <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'UAT|AnyCPU'">
    <OutputPath>binUAT</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>
  

Комментарии:

1. Это кажется еще одним супер простым способом изменить файлы app.config в соответствии с конфигурацией сборки. Майк, ты тестировал со стандартными конфигурациями отладки и выпуска?

2. 4 года спустя это помогло мне. Спасибо.

Ответ №6:

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

Ответ №7:

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

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

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

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

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

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

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

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

Помните, что если вы создаете папку App_Config (или как бы вы ее ни называли), различные промежуточные конфигурационные файлы должны иметь действие сборки = Нет и Копировать в выходной каталог = Не копировать.

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

 <Project>
<UsingTask TaskName="TransformXml" AssemblyFile="$(MSBuildExtensionsPath)MicrosoftVisualStudiov$(VisualStudioVersion)WebMicrosoft.Web.Publishing.Tasks.dll" />
<Target Name="TransformOnBuild" BeforeTargets="PrepareForBuild">
    <TransformXml Condition="Exists('App_Configapp.Base.config')" Source="App_Configapp.Base.config" Transform="App_Configapp.$(Configuration).config" Destination="app.config" />
    <TransformXml Condition="Exists('App_ConfigWeb.Base.config')" Source="App_ConfigWeb.Base.config" Transform="App_ConfigWeb.$(Configuration).config" Destination="Web.config" />
</Target>
  

Комментарии:

1. Я только что попробовал это в Visual Studio 2017, и это не работает. Стрелять. Я действительно надеялся, что это сработает, потому что это выглядит как самое простое в реализации.

2. Задача TransformXml не определена в примерах. Я добавляю запись. Вы можете определить его в файле mycustom.targets, который включается во все ваши проекты запуска в вашем решении.

3. @GregBurghardt, хочешь попробовать это сейчас?

4. Я мог бы попробовать. Я установил плагин Config Transform для Visual Studio, и это сработало действительно хорошо. Мне действительно интересно, делает ли плагин в основном то, что делает ваш ответ.

5. Хорошо, дайте мне знать, как это происходит.

Ответ №8:

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

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

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

Комментарии:

1. Безусловно, самый простой способ сделать то, что должно было быть очень простой и важной функцией, которая была испорчена чрезмерно мыслящими людьми! Спасибо Janbro.

Ответ №9:

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

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

Комментарии:

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

Ответ №10:

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

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

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