Преобразование App.Config для проектов, которые не являются веб-проектами в Visual Studio?

В Visual Studio 2010 для веб-приложений есть функции Config Transformation, с помощью которых мы можем поддерживать несколько файлов конфигурации для разных сред. Но такая же функция недоступна для файлов App.Config для Windows Services/WinForms или консольного приложения.

Существует обходное решение, предлагаемое здесь: Применение магии XDT к App.Config.

Однако это не просто и требует нескольких шагов. Есть ли более простой способ добиться того же для файлов app.config?

Ответ 1

Теперь это работает с Visual Studio AddIn, рассмотренным в этой статье: SlowCheetah - Web.config Синтаксис преобразования теперь обобщен для любого файла конфигурации XML.

Вы можете щелкнуть правой кнопкой мыши по вашему web.config и нажать "Добавить конфигурацию Transforms". Когда вы это сделаете, вы получите файл web.debug.config и web.release.config. Вы можете сделать web.whatever.config, если хотите, так как поскольку имя соответствует профилю конфигурации. Эти файлы это только изменения, которые вы хотите сделать, а не полную копию вашего web.config.

Возможно, вы захотите использовать XSLT для преобразования web.config, но в то время как они чувствуют себя интуитивно прав, это на самом деле очень много.

Здесь два преобразования: одно с использованием XSLT и одно с использованием XML Синтаксис/пространство имен документов Transform. Как и все несколько способов в XSLT сделать это, но вы получите общую идею. XSLT является обобщенным языком преобразования дерева, тогда как это развертывание один оптимизирован для определенного подмножества общих сценариев. Но классной частью является то, что каждое преобразование XDT является плагином .NET, поэтому вы можете сделать ваш собственный.

   
<?xml version="1.0" ?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:template match="@*|node()">
  <xsl:copy>           
    <xsl:apply-templates select="@*|node()"/>
  </xsl:copy>
</xsl:template>
<xsl:template match="/configuration/appSettings">
  <xsl:copy>
    <xsl:apply-templates select="node()|@*"/>
    <xsl:element name="add">
      <xsl:attribute name="key">NewSetting</xsl:attribute>
      <xsl:attribute name="value">New Setting Value</xsl:attribute>
    </xsl:element>
  </xsl:copy>
</xsl:template>
</xsl:stylesheet>

Или то же самое с помощью преобразования развертывания:

   
<configuration xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform">
   <appSettings>
      <add name="NewSetting" value="New Setting Value" xdt:Transform="Insert"/>
   </appSettings>
</configuration>

Ответ 2

Я попробовал несколько решений, и вот самое простое, которое я лично нашел.
Дан указал в комментариях, что оригинальное сообщение принадлежит Олегу Сычу -спасибо, Олег!

Вот инструкции:

1. Добавьте файл XML для каждой конфигурации в проект.

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

2. Выгрузите проект и откройте файл .csproj для редактирования

Visual Studio позволяет редактировать .csproj файлы прямо в редакторе - вам просто нужно сначала выгрузить проект. Затем щелкните его правой кнопкой мыши и выберите Изменить & lt; ProjectName & gt;.csproj.

3. Свяжите файлы конфигурации App. *. С основным файлом App.config

.Найдите раздел файла проекта, который содержит все ссылки App.config и App.*.config. Вы заметите, что их действия по сборке установлены на None:

<None Include="App.config" />
<None Include="App.Debug.config" />
<None Include="App.Release.config" />

Сначала установите для всех них действие сборки Content.
Затем сделайте все зависящие от конфигурации файлы зависимыми от основного App.config, чтобы Visual Studio сгруппировала их, как это делает дизайнер и файлы с выделенным кодом.

Замените XML выше на приведенный ниже:

<Content Include="App.config" />
<Content Include="App.Debug.config" >
  <DependentUpon>App.config</DependentUpon>
</Content>
<Content Include="App.Release.config" >
  <DependentUpon>App.config</DependentUpon>
</Content>

4. Активировать магию трансформации

В конце файла после

<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />

и до финала

</Project>

вставьте следующий XML:

  <UsingTask TaskName="TransformXml" AssemblyFile="$(MSBuildExtensionsPath)\Microsoft\VisualStudio\v$(VisualStudioVersion)\Web\Microsoft.Web.Publishing.Tasks.dll" />
  <Target Name="CoreCompile" Condition="exists('app.$(Configuration).config')">
    <!-- Generate transformed app config in the intermediate directory -->
    <TransformXml Source="app.config" Destination="$(IntermediateOutputPath)$(TargetFileName).config" Transform="app.$(Configuration).config" />
    <!-- Force build process to use the transformed configuration file from now on. -->
    <ItemGroup>
      <AppConfigWithTargetPath Remove="app.config" />
      <AppConfigWithTargetPath Include="$(IntermediateOutputPath)$(TargetFileName).config">
        <TargetPath>$(TargetFileName).config</TargetPath>
      </AppConfigWithTargetPath>
    </ItemGroup>
  </Target>

Теперь вы можете перезагрузить проект, собрать его и наслаждаться трансформациями App.config!

FYI

Убедитесь, что ваши файлы App.*.config настроены правильно:

<?xml version="1.0" encoding="utf-8"?>
<configuration xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform">
     <!--magic transformations here-->
</configuration>

Для новых версий Visual Studio

Для VS2017 и VS2019 (по крайней мере) вам больше не нужно выполнять шаг 4.

Ответ 3

Другим решением, которое я нашел, является НЕ использование преобразований, а просто отдельный файл конфигурации, например. app.Release.config. Затем добавьте эту строку в файл csproj.

  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x86' ">
    <AppConfig>App.Release.config</AppConfig>
  </PropertyGroup>

Это не только сгенерирует правильный файл myprogram.exe.config, но если вы используете проект установки и развертывания в Visual Studio для генерации MSI, это заставит проект развертывания использовать правильный файл конфигурации при упаковке.

Ответ 4

По моему опыту, вещи, которые мне нужны для создания специфичных для среды, - это такие вещи, как строки подключения, настройки приложений и часто настройки smpt. Система config позволяет указывать эти вещи в отдельных файлах. Поэтому вы можете использовать это в своем app.config/web.config:

 <appSettings configSource="appsettings.config" />
 <connectionStrings configSource="connection.config" />
 <system.net>
    <mailSettings>
       <smtp configSource="smtp.config"/>
    </mailSettings>
 </system.net>

То, что я обычно делаю, заключается в том, чтобы поместить эти разделы, зависящие от конфигурации, в отдельные файлы, в подпапку ConfigFiles (либо в корне решения, либо на уровне проекта). Я определяю файл для каждой конфигурации, например. smtp.config.Debug и smtp.config.Release.

Затем вы можете определить событие предварительной сборки следующим образом:

copy $(ProjectDir)ConfigFiles\smtp.config.$(ConfigurationName) $(TargetDir)smtp.config

В разработке команды вы можете настроить это дальше, включив в соглашение%% COMPUTERNAME% и/или% USERNAME%.

Конечно, это означает, что целевые файлы (x.config) НЕ должны быть помещены в исходный элемент управления (поскольку они сгенерированы). Вы все равно должны добавить их в файл проекта и установить для своего свойства типа вывода "copy always" или "copy if newer".

Простая, расширяемая и работает для всех типов проектов Visual Studio (консоль, winforms, wpf, web).

Ответ 5

Вдохновленный Олегом и другими в этом вопросе, я принял решение fooobar.com/questions/15095/... один шаг, чтобы включить следующее.

  • Работает с ClickOnce
  • Работает с проектами установки и развертывания в VS 2010
  • Работает с VS2010, 2013, 2015 (не тестировал 2012 год, хотя и должен работать).
  • Работает с Team Build. (Вы должны установить A) Visual Studio или B) Microsoft.Web.Publishing.targets и Microsoft.Web.Publishing.Tasks.dll)

Это решение работает, выполняя преобразование app.config до того, как app.config ссылается в первый раз в процессе MSBuild. Он использует файл внешних целей для упрощения управления несколькими проектами.

Инструкции:

Аналогичные шаги относятся к другому решению. Я процитировал то, что остается тем же, и включил его для полноты и более простого сравнения.

0. Добавьте новый файл в свой проект под названием AppConfigTransformation.targets

<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <!-- Transform the app config per project configuration.-->
  <PropertyGroup>
    <!-- This ensures compatibility across multiple versions of Visual Studio when using a solution file.
         However, when using MSBuild directly you may need to override this property to 11.0 or 12.0 
         accordingly as part of the MSBuild script, ie /p:VisualStudioVersion=11.0;
         See http://blogs.msdn.com/b/webdev/archive/2012/08/22/visual-studio-project-compatability-and-visualstudioversion.aspx -->
    <VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">10.0</VisualStudioVersion>
  </PropertyGroup>

  <Import Project="$(MSBuildExtensionsPath)\Microsoft\VisualStudio\v$(VisualStudioVersion)\Web\Microsoft.Web.Publishing.targets" />

  <Target Name="SetTransformAppConfigDestination" BeforeTargets="PrepareForBuild" 
          Condition="exists('app.$(Configuration).config')">
    <PropertyGroup>
      <!-- Force build process to use the transformed configuration file from now on. -->
      <AppConfig>$(IntermediateOutputPath)$(TargetFileName).config</AppConfig>
    </PropertyGroup>
    <Message Text="AppConfig transformation destination: = $(AppConfig)" />
  </Target>

  <!-- Transform the app.config after the prepare for build completes. -->
  <Target Name="TransformAppConfig" AfterTargets="PrepareForBuild" Condition="exists('app.$(Configuration).config')">
    <!-- Generate transformed app config in the intermediate directory -->
    <TransformXml Source="app.config" Destination="$(AppConfig)" Transform="app.$(Configuration).config" />
  </Target>

</Project>

1. Добавьте XML файл для каждой конфигурации в проект.

Как правило, у вас будут конфигурации Debug и Release, так что назовите свои файлы App.Debug.config и App.Release.config. В моем проекте я создал конфигурацию для каждого вида окружения, чтобы вы могли поэкспериментировать с этим.

2. Разгрузите проект и откройте файл.csproj для редактирования.

Visual Studio позволяет редактировать.csproj прямо в редакторе - вам просто нужно сначала выгрузить проект. Затем щелкните его правой кнопкой мыши и выберите Edit.csproj.

3. Bind App. *. Config файлы в основной файл App.config.

Найдите раздел файла проекта, содержащий все ссылки на App.config и App. *. Config и замените их следующим образом. Вы заметите, что вместо Content мы используем None.

<ItemGroup>
  <None Include="app.config"/>
  <None Include="app.Production.config">
    <DependentUpon>app.config</DependentUpon>
  </None>
  <None Include="app.QA.config">
    <DependentUpon>app.config</DependentUpon>
  </None>
  <None Include="app.Development.config">
    <DependentUpon>app.config</DependentUpon>
  </None>
</ItemGroup>

4. Активировать преобразования магии

В конце файла после

<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />

и до окончательного

</Project>

вставьте следующий XML:

<Import Project="AppConfigTransformation.targets" />

Готово!

Ответ 6

Вы можете использовать отдельный файл конфигурации для каждой конфигурации, например. app.Debug.config, app.Release.config, а затем используйте конфигурационную переменную в файле проекта:

<PropertyGroup>
    <AppConfig>App.$(Configuration).config</AppConfig>
</PropertyGroup>

Затем будет создан правильный файл ProjectName.exe.config в зависимости от конфигурации, в которой вы строите.

Ответ 7

Я написал красивое расширение для автоматизации преобразования app.config, как тот, который был создан в проекте веб-приложений Configuration Transform

Самое большое преимущество этого расширения заключается в том, что вам не нужно устанавливать его на всех машинах сборки

Ответ 9

Я столкнулся с следующей статьей, которая выглядит немного проще, но я сам не пробовал.

http://fknut.blogspot.com/2009/11/appconfig-transformation-with-new.html

Кроме того, в MS Connect есть запрос функций, который может стоить голоса, поэтому он включается во всю плату в следующем SP или версии.

https://connect.microsoft.com/VisualStudio/feedback/details/564414

Ответ 10

Итак, я немного изменил подход. Я последовал за Дэном через шаг 3, но добавил еще один файл: App.Base.Config. Этот файл содержит параметры конфигурации, которые вы хотите в каждом созданном приложении App.Config. Затем я использую BeforeBuild (с дополнением Yuri к TransformXml), чтобы преобразовать текущую конфигурацию с помощью Base config в App.config. Затем процесс сборки использует преобразованный файл App.config как обычно. Тем не менее, одно раздражение заключается в том, что вы хотите исключить постоянно изменяющийся App.config из исходного управления, но другие файлы конфигурации теперь зависят от него.

  <UsingTask TaskName="TransformXml" AssemblyFile="$(MSBuildExtensionsPath)\Microsoft\VisualStudio\v$(VisualStudioVersion)\Web\Microsoft.Web.Publishing.Tasks.dll" />
  <Target Name="BeforeBuild" Condition="exists('app.$(Configuration).config')">
    <TransformXml Source="App.Base.config" Transform="App.$(Configuration).config" Destination="App.config" />
  </Target>

Ответ 12

Я решаю эту проблему с помощью этого инструмента http://ctt.codeplex.com/. Я использую его с CCNet/nAnt script для создания пакетов.

Ответ 13

Просто небольшое усовершенствование решения, которое, кажется, теперь размещено повсюду:

<UsingTask TaskName="TransformXml" AssemblyFile="$(MSBuildExtensionsPath)\Microsoft\VisualStudio\v$(VisualStudioVersion)\Web\Microsoft.Web.Publishing.Tasks.dll" />
  • то есть, если вы не планируете оставаться с текущей версией VS навсегда

Ответ 14

Я создал еще одну альтернативу тому, которую разместил Vishal Joshi, где устранено требование изменить действие сборки на Контент, а также была реализована базовая поддержка развертывания ClickOnce. Я говорю basic, потому что я не тестировал его полностью, но он должен работать в типичном сценарии развертывания ClickOnce.

Решение состоит из одного проекта MSBuild, который после импорта в существующий проект приложения Windows (*.csproj) расширяет процесс сборки, чтобы рассмотреть преобразование app.config.

Вы можете прочитать более подробное объяснение в Visual Studio App.config XML Transformation, а файл проекта MSBuild может быть загружен из GitHub.

Ответ 15

Если вы используете онлайн-версию TFS (Cloud-версия) и хотите преобразовать приложение App.Config в проект, вы можете сделать следующее без установки каких-либо дополнительных инструментов. Из VS = > Выгрузить проект = > Изменить файл проекта = > Перейти к нижней части файла и добавить следующее:

<UsingTask TaskName="TransformXml" AssemblyFile="$(MSBuildExtensionsPath)\Microsoft\VisualStudio\v$(VisualStudioVersion)\Web\Microsoft.Web.Publishing.Tasks.dll" />
<Target Name="AfterBuild" Condition="Exists('App.$(Configuration).config')">
<TransformXml Source="App.config" Transform="App.$(Configuration).config" Destination="$(OutDir)\$(AssemblyName).dll.config" />

AssemblyFile и Destination работают для локального использования и онлайн-сервера TFS (Cloud).

Ответ 16

предлагаемое решение не будет работать, если библиотека классов с конфигурационным файлом ссылается на другой проект (в моем случае это была проектная библиотека Azure). Он не скопирует правильный преобразованный файл из папки obj в папку bin\##configuration-name##. Чтобы он работал с минимальными изменениями, вам нужно изменить AfterCompile target на BeforeCompile:

<Target Name="BeforeCompile" Condition="exists('app.$(Configuration).config')">