Multiple .NET configuration files and problem with installation project

To handle the settings for different deployment purposes, I moved the application settings from app.config to my own file and included this file in app.config via configSource. I also created a settings file for each purpose. Here is an illustration:

Project A app.config (references settings.config) settings.config settings.Release.config settings.Debug.config 

During post-build, I copy the corresponding settings. {configuration} .config to the output directory. While this works, and I see the settings.config file in the project output directory containing the settings for the current build configuration: Release, Debug, etc.

However, I had a problem with the installation project that I have for this project (project A). Initially, it did not include the settings.config file. So I installed the build action for the settings.config file as Content, and I added the content files from Project A to the installation project. This ensured that the settings.config file was included in the setting. However, since the installation project apparently selects the settings.config file from the project directory instead of the output directory, the settings.config file included in the configuration is not what it should be. I want one of the output directory to be included in the installer, since it is the right one for the current build configuration. I tried the following:

  • Added settings.config file as a file for the installation project. However, it seems that I can only indicate the absolute path. Therefore, when I add it from the output directory of a specific assembly configuration (..bin \ debug \ settings.config), it does not work in another assembly configuration because (..bin \ debug \ settings.config) exists in the directory specified. I studied the use of relative paths or dynamic paths in an installation project where the assembly configuration can be specified as part of the path, but I could not find anything.

I looked at using the pre-build event to actually modify the settings.config file in the project directory, and then copied it to the output directory, setting it to "Copy to output directory" to always copy or copy if it is newer. This should ensure that the corresponding settings.config file is copied to the output directory in the same way as the post-build solution, and also ensure that the contents of the settings.config file are updated before the installation project includes it. However, I do not like this solution because I have to make sure that the settings.config file can be written before I can make any changes, since it is controlled by the source. If it is read-only, then I need to flip it over for writing, make changes and then set it to read again. This adds extra complexity.

I was wondering if anyone has a better idea or knows the trick of the setup project, which allows me to include the settings.config file suitable for the current build configuration in the installer.

thanks

+4
source share
2 answers

If I had to approach this problem, I would start by asking:

Why should settings.config be controlled by the source code if settings.Debug.config or settings.Release.config provide the same information?

The answer, if I read your question correctly, is that you need to make the settings.config file appear as part of the assembly output. I assume this is because your setup project uses the built-in "Primary Output" option.

Instead, you can add this file to the installation project as an explicit link to the file. Right-click the installation project and select add / file, then select the file you want to include. As you noticed (if VS2008 has not been fixed, which, unfortunately, I have not yet been allowed to use at work), there is a very annoying restriction on manually added files - there is no way to configure the path construction. You can get around this by copying the appropriate settings.config file to a regular place (e.g. bin / Configuration) and selecting it there. This limits you to building versions of Debug and Release in series, rather than in parallel, but for many, this is probably not a big problem.

If you don't need VS setup projects, I highly recommend that you take a look at WiX (Windows Installer XML - see http://wix.sourceforge.net/ for more information). This will easily allow you to complete what you need, although if you are not familiar with the internal workings of Microsoft Installer, the initial learning curve may be a little steep. Microsoft uses WiX on its own for some fairly significant configuration tasks (such as Office 2007, SQL Server, etc.). It was hoped that WiX would become part of Visual Studio (for VS 2010), but, unfortunately, this is no longer the case.

+1
source

I decided to achieve the same result in a different way (having the opportunity to have different configuration settings for different target environments). So, here is how I implemented it, and it works great. I read some of the posts here in SO about the XmlMassUpdate task from the MSBuild Community Tasks and decided to use it. Here is what I did:

1) For each project, which should have different settings depending on the target environment, I added an xml file called app.config.substitutions.xml or web.config.substitutions.xml to the project. So the project looked like

 Project A app.config app.config.substitutions.xml 

The app.config.substitutions.xml file contains parameter substitutions that XmlMassUpdate will process and apply to the app.config file. The following is an example of the replacement file I am using:

 <configuration xmlns:xmu="urn:msbuildcommunitytasks-xmlmassupdate"> <substitutions> <Development> <appSettings> <add xmu:key="key" key="SomeSetting" value="DevValue" /> </appSettings> </Development> <Test> <appSettings> <add xmu:key="key" key="SomeSetting" value="TestValue" /> </appSettings> </Test> <Release> <appSettings> <add xmu:key="key" key="SomeSetting" value="ReleaseValue" /> </appSettings> </Release> </substitutions> </configuration> 

For more information on how to specify substitutions, see the documentation for XmlMassUpdate or just search on it.

2) Now I need to run XmlMassUpdate as part of the build automation (TeamBuild / MSBuild). Therefore, in the BeforeCompile file in the TeamBuild assembly definition file (mainly in the proj file), I added the following to run XmlMassUpdate in the configuration files that have the corresponding .substitution.xml file

  <PropertyGroup> <SubstitutionFileExtension>.substitutions.xml</SubstitutionFileExtension> <TargetEnvironment>Test</TargetEnvironment> </PropertyGroup> <Target Name="BeforeCompile" Condition="'$(IsDesktopBuild)'!='true'"> <CreateItem Include="$(SolutionRoot)\**\app.config;$(SolutionRoot)\**\web.config"> <Output ItemName="ConfigurationFiles" TaskParameter="Include"/> </CreateItem> <CreateItem Include="@(ConfigurationFiles)" Condition="Exists('%(FullPath)$(SubstitutionFileExtension)')"> <Output ItemName="ConfigFilesWithSubstitutions" TaskParameter="Include"/> </CreateItem> <Message Text="Updating configuration files with deployment target specific settings..."/> <XmlMassUpdate ContentFile="%(ConfigFilesWithSubstitutions.FullPath)" SubstitutionsFile="%(ConfigFilesWithSubstitutions.FullPath)$(SubstitutionFileExtension)" ContentRoot="/configuration" SubstitutionsRoot="/configuration/substitutions/$(TargetEnvironment)"/> </Target> 

Please note that the configuration files are read-only during build, so you must set them up for writing before completing this task. Actually, I have another MSBuild custom task that runs before XmlMassUpdate, which handles general settings in all configuration files, such as connection strings. This task allows you to write configuration files. I also do not check the changed configuration files back to the original control. They (the appropriate configuration file for deployment purposes) are included in the installer.

+1
source

All Articles