Easily switching between App.Config files with MSBuild

Imagine the following situation: One codebase, two customers with different Application Configuration files. How can we easily switch between the different configurations? By taking advantage of the Build Configurations functionality in Visual Studio we can easily switch between different configurations:

screenshot of the configuration manager in visual studio

A brute-force solution would be to add a Post-build Event that copies the desired App.Config file to the destination directory. In the Microsoft.Common.targets file (usually at C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727) around line 725 you can read how MSBuild chooses the App.Config that is copied to the destination folder:

Choose exactly one app.config to be the main app.config that is copied to the destination folder.

The search order is:

  1. Choose the value $(AppConfig) set in the main project.
  2. Choose @(None) App.Config in the same folder as the project.
  3. Choose @(Content) App.Config in the same folder as the project.
  4. Choose @(None) App.Config in any subfolder in the project.
  5. Choose @(Content) App.Config in any subfolder in the project.

Thus, simply setting $(AppConfig) should be enough to make sure that MSBuild chooses the appropriate App.Config file. Here is an example of a csproj section that defines $(AppConfig) as App.Customer1.Config or App.Customer2.Config depending on the choosen Build configuration:

<propertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug Customer1|AnyCPU' ">
 <debugSymbols>true</debugSymbols>
 <debugType>full</debugType>
 <optimize>false</optimize>
 <outputPath>bin\Debug\</outputPath>
 <defineConstants>DEBUG;TRACE</defineConstants>
 <errorReport>prompt</errorReport>
 <warningLevel>4</warningLevel>
 <appConfig>App.Customer1.Config</appConfig>
</propertyGroup>
<propertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug Customer2|AnyCPU' ">
 <debugSymbols>true</debugSymbols>
 <outputPath>bin\Debug Customer2\</outputPath>
 <defineConstants>DEBUG;TRACE</defineConstants>
 <debugType>full</debugType>
 <platformTarget>AnyCPU</platformTarget>
 <codeAnalysisUseTypeNameInSuppression>true</codeAnalysisUseTypeNameInSuppression>
 <codeAnalysisModuleSuppressionsFile>GlobalSuppressions.cs</codeAnalysisModuleSuppressionsFile>
 <errorReport>prompt</errorReport>
 <appConfig>App.Customer2.Config</appConfig>
  </propertyGroup>

7 Comments.

  1. Does it work with Web projects…I tried it and it does not seem to work. Do you have any workaround for a web project so I can have multible web.[Build].config but choose only the config on the type of build?

  2. I’m confused…I’m not familiar with MSBuild. I’ve got a vbproj, and I can’t find any file that resembles that xml build file anywhere.
    I’ve added a new solution configuration, now where do I go to make it pick up a different app.config?

  3. Don’t worry I found it in .vbproj. Explorer doesn’t do a very good job of searching for files.

  4. Awesome post. I’m just now stumbling on it after begging the goog to answer me. I ended up using a modified version of this where I included the configuration name in the file name of the app config for that configuration. Then all I had to do was add a single line and the build auto-magically picks the correct config file.

    Ex App.Config file names.
    App.Debug.Config
    App.Release.Config

    Simply added App.$(ConfigurationName).Configto the project file in it’s own PropertyGroup and Done.

    Thanks again.

  5. These days i would strongly recommend that you look into the Web.Config transformation syntax (eg: here.)

    Or use something completely different if you don’t want to couple your configuration system to your build configuration system.

  6. Yury Schkatula

    Agree with timvw, transformation syntax is really powerful feature. And you can apply it to any XML-styled file in your project. If you don’t mind, let me post an example for sitemap transformation:
    http://windowsasusual.blogspot.ru/2012/01/live-like-you-were-webconfig.html

Trackbacks and Pingbacks: