How to select different app.config for several build configurations

I have a dll-type project that contains MSTest integration tests. On my machine the tests pass, and I want the same to happen on a CI server (I use TeamCity). But the tests fail, because I need to tweak some settings in app.config. This is why I was thinking to have a separate second app.config file that will hold the settings for CI server.

So I would like to have

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

Thus if I select Release configuration in build config on CI, I would like to use app.Release.config file instead of app.config

Problem
This doesn't seem to be straightforward for simple .dll type projects. For web projects, I can do web config transformations. I found a hack how to do these transformations for a dll type project, but I am not a big fan of hacks.

Question
What is a standard approach to tweak app.config files depending on build config for .NET projects (such as Debug, Release, ...)?

121371 次浏览

你应该考虑 ConfigGen。就是为了这个目的研发的。它基于模板文件和设置文件为每台部署计算机生成一个配置文件。我知道这不能明确回答你的问题,但是它可能很好地回答了你的问题。

So rather than Debug, Release etc, you might have Test, UAT, Production etc. You can also have different settings for each developer machine, so that you can generate a config specific to your dev machine and change it without affecting any one else's deployment.

一个使用的例子可能是..。

<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)开关指定的生成的配置。

你可以尝试以下方法:

  1. 在解决方案资源管理器中右键单击项目并选择 卸载项目
  2. 将卸载该项目。再次右键单击该项目并选择 Edit <YourProjectName>.csproj
  3. 现在可以在 VisualStudio 中编辑项目文件。
  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文件的方法,但是它对于 VisualStudio 项目的其他项目非常有效。您可以以几乎任何您喜欢的方式自定义生成过程。无论如何,让我知道结果。

我使用 XmlPreprocess tool进行配置文件操作。它为多个环境使用一个映射文件(在您的情况下是多个构建目标)。可以通过 Excel 编辑映射文件。它非常容易使用。

使用 慢猎豹插件。要了解更多如何使用 SlowCheetah 的选项和细节,请继续阅读。

正如您已经注意到的,对于 Library type (.dll)项目,没有使用不同配置文件的默认方法和简单方法。原因是当前的想法是: “你不需要”!框架开发人员认为需要对可执行文件进行配置: 可以是控制台、桌面、 Web、移动应用程序或其他东西。如果您开始为 DLL提供配置,您可能会得到一个我可以称之为 配置地狱的东西。您可能不再理解(容易地)为什么这个和那个变量有这样奇怪的值似乎不知道从哪里冒出来。

“等等”,-您可能会说,“但是我需要这个来进行集成/单元测试,而且 是的需要一个库!”.这是真的,这就是你能做的(只选一个,不要混在一起) :

1. SlowCheetah - transforms current config file

您可以安装 慢猎豹-一个 VisualStudio 插件,它可以为您完成所有低级 XML 插入(或转换)。它的工作方式,简而言之:

  • 安装 SlowCheetah 并重新启动 Visual Studio (Visual Studio > Tools > Extended and Update... > Online > Visual Studio Gallery > 搜索“ Slow Cheetah”)
  • 定义您的解决方案配置(默认情况下有 调试放手) ,您可以添加更多(右键单击 解决方案资源管理器 > 配置管理器..。 > 主动解决方案配置 > 新..。中的解决方案)
  • 如果需要,添加一个配置文件
  • 右键单击配置文件 > < em > 添加变换
    • 这将创建转换文件-每个配置一个
    • 转换文件作为注入器/变换器工作,它们在原始配置文件中找到所需的 XML 代码,并注入新行或变换所需的值,无论您让它做什么

2. 修改.proj 文件-copy-重命名一个全新的配置文件

最初取自 here。这是一个自定义 MSBuild 任务,可以将其嵌入到 VisualStudio。 Proj文件中。将下面的代码复制并粘贴到项目文件中

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

现在在项目中创建一个名为 Config的文件夹,并在其中添加新文件: App. Debug.configApp. Release.config等。现在,根据您的配置,VisualStudio 将从 Config文件夹中选择配置文件,并将其复制-重命名到输出目录中。因此,如果您选择了 PatternPA.Test.Integration项目和 调试配置,在构建后的输出文件夹中,您将发现一个从 Config\App.Debug.config复制并在构建后重命名的 PatternPA.Test. Integration.dll.config文件。

These are some notes you can leave in the config files

<?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>

在 VisualStudio 中,您可以使用类似的东西

Project structure

3. 在 VisualStudio 之外使用脚本文件

每个构建工具(如 NAntMSBuild)都将根据配置提供转换配置文件的能力。如果您在生成机器上生成解决方案,那么这非常有用,因为您需要对准备发布产品的内容和方式进行更多的控制。

例如,您可以使用 web 发布 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>

使用与《罗密欧》相同的方法,我把它改编成了 Visual Studio 2010:

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


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

这里需要将两个 App.config 文件都保存在不同的目录中(appDebug 和 appRelease)。 我测试过了,效果很好!

在对管理开发和构建的配置等进行了一些研究之后,我决定使用我自己的配置,我已经在 bitbucket 上提供了它: https://bitbucket.org/brightertools/contemplate/wiki/Home

这个用于多个环境的多个配置文件是一个基本的配置条目替换工具,可以使用任何基于文本的文件格式。

Hope this helps.

VisualStudio Gallery 中的 SlowCheetah 和 FastKoala 似乎是解决这个问题的非常好的工具。

但是,如果您希望避免使用 addins 或者在构建/集成过程中更广泛地使用它们实现的原则,那么将它添加到 msbuild * proj 文件中是一个简短的修复方法。

注意: 这或多或少是对@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 = Nothing,并且复制到 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>

See if the XDT (web.config) transform engine can help you. Currently it's only natively supported for web projects, but technically there is nothing stopping you from using it in other application types. There are many guides on how to use XDT by manually editing the project files, but I found a plugin that works great: https://visualstudiogallery.msdn.microsoft.com/579d3a78-3bdd-497c-bc21-aa6e6abbc859

The plugin is only helping to setup the configuration, it's not needed to build and the solution can be built on other machines or on a build server without the plugin or any other tools being required.

我用我在这里找到的解决办法解决了这个问题: Http://www.blackwasp.co.uk/switchconfig.aspx

简而言之,他们声称: “通过添加一个构建后事件。[ ... ]我们需要添加以下内容:

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

我听说过 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>