How to merge xml app.config files outside of the build process - c#

I would like to use app.config files for settings, but I don't want to have to select different build configurations to select which settings to use, I would rather everything build in release and then just the app.config file be different when the application is deployed.
What is a good way to merge two xml files together so that I can deploy the correct settings to the correct environment? I have found several solutions that are based on selecting different build configurations and the transform happens at build time, but I want the transform to just be from a command line utility that my deploy script can run

At my company, we use the Web Config Transformation Runner, available on GitHub. It may be invoked directly from the command line, a bit like this:
D:\Utils\WebConfigTransformRunner.exe App.config App.production.config App.config
We've incorporated this into a larger packaging and deployment process to handle deploying to our various environments.

Related

DevOps for ASP.NET MVC: Running a web.config transform in a separate step, after building and packaging

I have an ASP.NET MVC app with multiple web.config transforms. I am using TeamCity to build and deploy the application using WebDeploy.
I want to be able build and package in Release mode in one TeamCity build. I want a second build to take the package from the first build, run a web.config transform for a specific environment, and deploy to that environment.
I have done this with Octopus Deploy, because it has a feature to run web.config transforms on a given NuGet package.
How can I accomplish this using msbuild and WebDeploy? They seem to tie the web.config transform closely to the process of compiling code. I'd rather not compile code once for each environment.
It might be possible to use a powershell step as a build step to transform your config for a specific environment. That way you don't need to compile the code in each build configuration for each environment.
There's an example here: Web config transforms outside of msbuild and I've also seen a suggestion to create a 'meta-runner' in Team City which should make it easier to apply this to multiple projects. Working with Meta-Runners
We had this same problem but found the newer Parameterization feature in WebDeploy fits this use case perfectly! ConfigTransforms (and SlowCheetah) use MSBuild and happen at build time. Parameterization is built into WebDeploy and provides transformation of files at deploy time.
Parameterization is more powerful than ConfigTransforms because it supports transformation of any text file type (.txt, .php, .sql, etc) not just xml files.
Basically you create a parameters.xml file that defines how/what you want to transform and then setParameters files for each environment/target thats basically just a dictionary (key/value pairs) for the config changes. We typically name these setParameters.[env].xml.
See the following links for more information:
Parameterization Primer
WebDeploy Parameterization Replace/Insert/Remove
ParameterizationPreview Plugin
I ended up doing this with a TransformXml step in an MSBuild file. Here's the process:
Build the web project with DeployOnBuild=true
Use Powershell to make a copy of the output package for each server
Use Powershell to invoke msbuild using a project file with only a TransformXml target, to run the appropriate transform for each server.

Using one app.config file for multiple projects

I have a solution with the following setup:
X amount of class library projects
Y amount of console application projects
Each of these projects may have 0 or more configuration parameters.
Now, I'd like to have only one App.config for user to specify settings and that App.config will only contain parameters of all the reference projects of the console application project to be run.
I've tried giving each project a Settings file and then linking them to the console applications according to their dependencies but that didn't work.
I've also tried just lumping all the configurations together in one class library project and have each console application link to that app.config (or settings file). But that also didn't work (i.e. changes of the app.config or the settings file in the class library will not update the .config of the executable)
Is what I am trying to do possible?
Yes, it is possible. You just need to open the app file. Follow the next example:
ConfigurationManager.OpenExeConfiguration("C:\Test\SomeProject.dll");
XmlNode loggingConfigNode = ConfigurationManager.GetSection("log4net") as XmlNode;
I guess that you will have to open each setting file in order to use the settings, or you will have to consolidate all the settings in a single app.config and then your applications can access the file by open it.

Common app.config for multiple applications

I have several C# console applications, which need to have the same set of settings. I want to avoid duplicity and avoid separate app.config for each application.
Is there any way to read a common app.config file (say common.config) for applications (app1.exe, app2.exe).
Create one file called app.config. Put it in some place outside of your projects' directories, like up in the solution directory. Add it to your projects as a linked item with a relative path to the file. Set the right build action for this item (application configuration) in each project.
Now when each project builds, the file will be copied to the project's output dir with the right name.
You can load an external app.config using the code below:
config = ConfigurationManager.OpenExeConfiguration(Path.Combine("C:\test\root", "Master.exe"));
string logpath = config.AppSettings.Settings["Log.Path"].Value;
And save settings as so:
config = ConfigurationManager.OpenExeConfiguration(Path.Combine("C:\test\root", "Master.exe"));
config.AppSettings.Settings["Log.Path"].Value = "C:\newpath";
config.Save();
You might have to have a master config within one of the applications and point the rest to this. Typically this method is considered bad practice though. There might be issues with different applications locking the file.
#Ran's answer is an option, but each application will still have its own config file after you build. At compile time they will be the same, but at deploy time they are copies.
You can also open one application's config file from another application using:
ConfigurationManager.OpenExeConfiguration(string)
You can have an external config file that all applications reference using:
ConfigurationManager.OpenMappedExeConfiguration
And there's the option to using the Machine config file using:
ConfigurationManager.OpenMachineConfiguration()

Configuration files per environment

I'm working on a project with several environments (Local,Development,Main,Prod,Live) that have several config files (Web, ConnectionStrings Windsor, Smtp, Appsettings, Nlog, etc).
The current strategy used is to have one of these config for each branch and to maintain the configs by hand and not to merge any changes.
What are the more elegant options for storing and deploying config files in this sort of set up?
Generally I tried to keep most of these settings in the appSettings (even though I know that's not the "official" right place for them). Then I break the appSettings out into an environment.config file, and have the appSetting element in the web.config reference that through the configSource attribute.
When I setup a new environment, I manually setup the environment.config file for that environment. When, when I deploy a new release, I exclude the environment.config file from teh deployment so that the environment-specific version stays in place.
This lets you deploy new copies of the web.config to include project-related changes, while keeping all of your truly environment-specific settings in a seperate place.
An elegant solution is to use WebDeploy (from Microsoft) for the deployment of your web app. When you run the deployment, you can specify a site specific parameter file which will be used the replace several values in the web.config file.
For deployment, WebDeploy uses a deployment packge, which Visual Studio or msbuild can create.
That way, we have a single deployment package that we can first deploy on a test system, run through several tests and then, when it passes the test, deploy without changes on several servers. Each server has its local parameter file that hardly ever changes and contains the site specific values.
store them on a file server that has the same name in all environments. I am not familiar with all of the configs, but most have ways of doing this. The only problem with this approach is usually dev/local which often share a file server so you have to change the local by hand.
If you actually can't point the configs to a file server, a less elegant solution would be to pull them down via a bat file at deployment or start up. seems like there are alot of options rather than maintaining by hand, that is error prone.

Manage multiple app config files during development

I'm building an application that is used by several different customers. Each customer has a fair amount of custom business logic, which I have cleverly refactored out into an assembly that gets loaded at runtime. The name of that assembly, along with a number of other customer-specific settings, are stored in the application's configuration file.
Right now, here's what I have to do in order to debug the application for customer foo:
Go to the filesystem in my project directory and delete app.config
Copy app.config.foo to app.config.foo - Copy.
Rename app.config.foo - Copy as app.config.
Tell Windows that yes, I want to change the file's extension.
Switch back to Visual Studio.
Open the Settings.settings item in my project.
Click "Yes" 13 or 14 times as VS asks me if I want to use the new settings that have been changed in app.config.
Close Settings.settings.
Okay! Now I'm ready to debug!
It seems to me that the rigamarole of opening Settings.settings is, or ought to be, unnecessary: I don't need the default values in Settings.cs to be regenerated, because I don't use them. But it's the only way I know of to make VS aware of the fact that the app.config file has changed, so that the build will copy it to the output directory.
There's got to be an easier way of doing this. What is it?
You can also let Visual Studio automate Robert`s approach by:
Define a Build Configuration for each client
In the post build event, simply xcopy app.config.xxx to your bin folder. Where XXX is the name of a Build Config accessible in VS. Something like: xcopy app.config.$(ConfigurationName) $(OutDir)/app.config
VS will drop a distinct build for your clients in separate folders, aolong with the proper config file.
bin/Client1/
bin/Client2/
You can refer this post for some good practices : Managing Multiple Configuration File Environments with Pre-Build Events
Thinking about the mess of managing multiple configuration files I made this tool: http://envride.codeplex.com/
Its purpose its exactly to make it easier to manage multiple configuration files in an automated way. I would be very pleased if you would take a look at it.
A couple of people suggested using multiple VS configurations, which I think would have worked, except that it would require me to rebuild the solution every time I switched between configurations.
What I did instead seemed a little stupid while I was doing it, but I've been using it for nearly a year now and it works extremely smoothly. In my project directly, I create a separate app.config.XXX file for each customer. The actual app.config file is used solely to generate Settings.cs - it has all of the correct setting names and their default values. It doesn't get copied to the build directories, ever.
Then I wrote a little program that lets me select a customer, and that simply goes through the directories for each project and, if I selected customer XXX, copies app.config.XXX to bin\debug\myprogram.exe.config and bin\release\myprogram.exe.config. As long as this program knows where the root of the solution is (I have to be a little careful whenever I branch the code), it works like a charm.
This thread is too old to represent current tools in VS.
You can use an addon that acts similar to web.debug.config but for app.config.
https://marketplace.visualstudio.com/items?itemName=GolanAvraham.ConfigurationTransform
And for the same app.config transformations without addon.
https://www.linkedin.com/pulse/multi-appconfig-visual-studio-2017-benjamin-davis/
You may opt to define multiple Visual Studio solution configurations, one for each customer, and have customised MSBuild targets for your Windows app project.
I have documented the steps of how I handled this here. Multiple app.config files for deploying to different environments
After a little digging and work around I got my Test project working with multiple configurations,
In the Configuration Manager, create the configurations you need
Copy paste your app.config and add the name of the configuration, in my case is AHI, FIV, MGC, so my config files look like: App.AHI.config, App.MGC.config, App.FIV.Config. You can name it how ever you wanted, but keep the same convention
Add a Post-Build event. In my case it would look like: xcopy $(ProjectDir)app.$(ConfigurationName).config $(TargetDir)$(TargetName).dll.config /y
here is my post, so you can read it with more details
Running a Test Project with Multiple Configurations

Categories