You cannot use multiple configuration files (i.e. one per library project) without coding.
config (or any file) when you press F5 in Visual Studio. You can have different transformations based on the build configuration. This will enable you to easily have different app settings, connection strings, etc for Debug versus Release. If you want to transform other files you can do that too.
Application configuration files Executable–hosted app. These apps have two configuration files: a source configuration file, which is modified by the developer during development, and an output file that is distributed with the app.
Use SlowCheetah plugin. For more options and details of how to use SlowCheetah keep reading.
As you have already noticed, there is no default and easy way to use different config files for a Library type (.dll) project. The reason is that the current thinking is: "You don't need to"! Framework developers reckon you need configuration for the executable file: be it a console, desktop, web, mobile app or something else. If you start providing configuration for a dll, you may end up with something I can call a config hell. You may no longer understand (easily) why this and that variables have such weird values coming seemingly from nowhere.
"Hold on", - you may say, "but I need this for my integration/unit testing, and it is a library!". And that is true and this is what you can do (pick only one, don't mix):
You can install SlowCheetah - a Visual Studio plug-in that does all low level XML poking (or transformation) for you. The way it works, briefly:
Originally taken from here. It's a custom MSBuild task that you can embed into Visual Studio .proj file. Copy and paste the following code into the project file
<Target Name="AfterBuild">
<Delete Files="$(TargetDir)$(TargetFileName).config" />
<Copy SourceFiles="$(ProjectDir)\Config\App.$(Configuration).config"
DestinationFiles="$(TargetDir)$(TargetFileName).config" />
</Target>
Now create a folder in the project called Config
and add new files there: App.Debug.config, App.Release.config and so on. Now, depending on your configuration, Visual Studio will pick the config file from a Config
folder, and copy-rename it into the output directory. So if you had PatternPA.Test.Integration project and a Debug config selected, in the output folder after the build you will find a PatternPA.Test.Integration.dll.config file which was copied from Config\App.Debug.config
and renamed afterwards.
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>
In Visual Studio you can have something like this
Each build tool (like NAnt, MSBuild) will provide capabilities to transform config file depending on the configuration. This is useful if you build your solution on a build machine, where you need to have more control on what and how you prepare the product for release.
For example you can use web publishing dll's task to transform any config file
<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>
You can try the following approach:
<ItemGroup> <None Include="App.config"/> </ItemGroup>
<ItemGroup Condition=" '$(Configuration)' == 'Debug' "> <None Include="App.Debug.config"/> </ItemGroup> <ItemGroup Condition=" '$(Configuration)' == 'Release' "> <None Include="App.Release.config"/> </ItemGroup>
I have not tried this approach to app.config
files, but it worked fine with other items of Visual Studio projects. You can customize the build process in almost any way you like. Anyway, let me know the result.
Using the same as approach as Romeo, I adapted it to Visual Studio 2010 :
<None Condition=" '$(Configuration)' == 'Debug' " Include="appDebug\App.config" />
<None Condition=" '$(Configuration)' == 'Release' " Include="appRelease\App.config" />
Here you need to keep both App.config files in different directories (appDebug and appRelease). I tested it and it works fine!
You should consider ConfigGen. It was developed for this purpose. It produces a config file for each deployment machine, based on a template file and a settings file. I know that this doesn't answer your question specifically, but it might well answer your problem.
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.
An example of usage might be...
<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>
If you place this in your .csproj file, and you have the following files...
$(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>
... then this will be the result...
From the first command, a config file generated for each environment specified in the xls file, placed in the output directory $(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>
From the second command, the local App.config used on your dev machine will be replaced with the generated config specified by the local (-l) switch and the filename (-n) switch.
I have heard good things about SlowCheetah, but was unable to get it to work. I did the following: add am tag to each for a specific configuration.
Ex:
<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>
I'm using XmlPreprocess tool for config files manipulation. It is using one mapping file for multiple environments(or multiple build targets in your case). You can edit mapping file by Excel. It is very easy to use.
SlowCheetah and FastKoala from the VisualStudio Gallery seem to be very good tools that help out with this problem.
However, if you want to avoid addins or use the principles they implement more extensively throughout your build/integration processes then adding this to your msbuild *proj files is a shorthand fix.
Note: this is more or less a rework of the No. 2 of @oleksii's answer.
This works for .exe and .dll projects:
<Target Name="TransformOnBuild" BeforeTargets="PrepareForBuild">
<TransformXml Source="App_Config\app.Base.config" Transform="App_Config\app.$(Configuration).config" Destination="app.config" />
</Target>
This works for web projects:
<Target Name="TransformOnBuild" BeforeTargets="PrepareForBuild">
<TransformXml Source="App_Config\Web.Base.config" Transform="App_Config\Web.$(Configuration).config" Destination="Web.config" />
</Target>
Note that this step happens even before the build proper begins. The transformation of the config file happens in the project folder. So that the transformed web.config is available when you are debugging (a drawback of SlowCheetah).
Do remember that if you create the App_Config folder (or whatever you choose to call it), the various intermediate config files should have a Build Action = None, and Copy to Output Directory = Do not copy.
This combines both options into one block. The appropriate one is executed based on conditions. The TransformXml task is defined first though:
<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>
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With