Як вибрати різні app.config для кількох конфігурацій збірки


115

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

Тому я хотів би мати

/ Слн
 / Прой
  app.config (я думаю, що цього вимагає VS)
  app.Release.config (Це окремий незалежний файл конфігурації)

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

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

Запитання
Що таке стандартний підхід до налаштування файлів app.config залежно від конфігурації збірки для .NET-проектів (таких як налагодження, випуск, ...)?

Відповіді:


154

Використовуйте плагін SlowCheetah . Щоб отримати додаткові параметри та детальну інформацію про використання SlowCheetah, читайте.

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

"Тримайся", - ви можете сказати, "але мені це потрібно для моєї інтеграції / тестування одиниць, і це бібліотека!". І це правда, і ось що ви можете зробити (виберіть лише один, не змішуйте):

1. SlowCheetah - перетворює поточний файл конфігурації

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

  • Встановіть SlowCheetah та перезапустіть Visual Studio (Visual Studio> Інструменти> Розширення та оновлення ...> Інтернет> Visual Studio Gallery> пошук "Повільний гепард")
  • Визначте конфігурації рішення ( налагодження та випуск за замовчуванням є), ви можете додати більше (клацніть правою кнопкою миші на рішення в Провіднику рішень > Менеджер конфігурацій ... > Конфігурація активного рішення > Нове ...
  • Додати необхідний конфігураційний файл
  • Клацніть правою кнопкою миші на конфігураційний файл> Додати перетворення
    • Це створить файли трансформації - по одному на вашу конфігурацію
    • Файли трансформації працюють як інжектори / мутатори, вони знаходять потрібний XML-код у вихідному конфігураційному файлі та вводять нові рядки або мутують необхідне значення, як би ви не говорили.

2. Fiddle з .proj-файлом - скопіюйте-перейменуйте цілком новий конфігураційний файл

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

<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 та конфігурація налагодження , у папці виводу після збірки ви знайдете файл 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ціль викликається за замовчуванням. Слід швидко виправити випадок опублікування
oleksii

1
Використовували ваш другий метод (свого роду). Перейшов до властивостей проекту та відредагував програму BeforeBuild, щоб скопіювати те, що App.<Target>.configперебуває App.configу проектному реєстрі , а не вихідному режимі.
SparK

@oleksii Ви маєте рацію. Але я все ще не міг знайти ціль, яку використовує мій процес веб-публікації (у Visual Studio 2013).
Massood Khaari

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

23

Ви можете спробувати наступний підхід:

  1. Клацніть правою кнопкою миші на проект в Провіднику рішень і виберіть Розвантажити проект .
  2. Проект буде завантажений. Клацніть правою кнопкою миші проект ще раз і виберіть Правка <Ім'я вашої програми> .csproj .
  3. Тепер ви можете редагувати файл проекту всередині Visual Studio.
  4. Знайдіть місце у файлі * .csproj, де включений файл конфігурації програми. Це буде виглядати так:
    <ItemGroup>
        <None Include = "App.config" />
    </ItemGroup>
  1. Замініть ці рядки такими:
    <ItemGroup Condition = "'$ (Конфігурація)' == 'Налагодження'">
        <None Include = "App.Debug.config" />
    </ItemGroup>

    <ItemGroup Condition = "'$ (Конфігурація)' == 'Випустити'">
        <None Include = "App.Release.config" />
    </ItemGroup>

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


Tnx для відповіді, але це не працює з app.config. VS вимагає обов'язкового app.configі не застосовує конфігурацію випуску, якщо я використовую VS build або Teamcity VS sln runner run.
олексій

2
Ось пояснює, як це зробити: Увімкнути app.debug.config app.release.config
Gabrielizalo

1
Чому за цю відповідь так багато голосів? Я спробував це, і це не працює. Насправді в режимі налагодження та випуску немає файлу App.config, а отже, у вихідній папці немає відповідного файла. Файли App.Debug.config і App.Release.config не мають жодного значення для Visual Studio.
MarkusParker

Це не працює: .csproj не можна відкрити, повідомлення про помилку "елементи поза цільовими елементами повинні мати: Включити, оновити або видалити"
Ело

12

Вам слід розглянути ConfigGen . Для цього він був розроблений. Він створює конфігураційний файл для кожної машини розгортання на основі файлу шаблону та файла налаштувань. Я знаю, що це не відповідає конкретно на ваше запитання, але це може відповісти на вашу проблему.

Отже, замість налагодження, випуску тощо, у вас можуть бути 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
Tnx для відповіді, це виглядає непогано. Але є деякі недоліки, він показує лише 75 завантажень (таким чином, він не зрілий), і він працює лише з .xls або .xlsx. Я не хочу дуже залежати від іншого спеціального формату документа для простих операцій. Я шукав більш стандартний підхід ...
олексій

2
Справедливий момент, хоча в ньому написано 194 завантаження на CodePlex, xls - це електронна таблиця, навряд чи спеціальний формат, і я знаю про три основні інвестиційні банки, які схвалили це для використання, тож якщо це досить добре для них ... Крім того, один Наразі запитуваних функцій є використання xml для налаштувань. Він майже готовий, але я все-таки віддаю перевагу підходу електронних таблиць. Набагато простіше побачити кожну обстановку для кожного середовища в табличному вигляді
Даніель Дайсон

Зараз ми перебуваємо на завершальній стадії тестування версії configGen, яку можна використовувати для генерування простих текстових файлів, а не лише xml. Тож якщо ви хочете генерувати css, sql, javascript тощо для середовища, слідкуйте за сайтом configGen
Даніель Дайсон

дякую Даніелю за рішення, саме це я шукав. Я спробую.
Бхупіндер Сінгх

10

Використовуючи такий же підхід, як і Ромео, я адаптував його до 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. Він дуже простий у використанні.


3

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 (або як ви її вирішите називати), різні проміжні конфігураційні файли повинні мати збірку дій = немає і скопіювати у вихідний каталог = не копіювати.

Це об'єднує обидва варіанти в один блок. Відповідна виконується на основі умов. Завдання 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>


Я просто спробував це у Visual Studio 2017, і це не працює. Стріляти. Я дуже сподівався, що це спрацює, адже це виглядає як найпростіший у виконанні.
Грег Бургхардт

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

@GregBurghardt, ви хочете спробувати зараз?
Еніола

Я можу спробувати. Я встановив плагін Config Transform для Visual Studio, і це спрацювало дуже добре. Мені справді цікаво, чи плагін в основному робить те, що робить ваша відповідь.
Грег Бургхардт

Гаразд, дайте мені знати, як це йде.
Еніола

1

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

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


Це зараз має відповісти. Щойно спробував це на 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

На сьогодні найпростіший метод зробити те, що повинно було бути дуже простою і важливою функцією, яку накрутили надмірно мислителі! Дякую Янбро.
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

Це декілька файлів конфігурації для кількох середовищ, його основний інструмент заміни конфігурації, який буде працювати з будь-яким текстовим файловим форматом.

Сподіваюся, це допомагає.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.