Single click builds for different environments using Visual Studio

A neat build system is vital for all projects. Good build system should be capable to work without *any* user intervention. Here is what Joel Spolsky says on his post

Can you make a build in one step?

By this I mean: how many steps does it take to make a shipping build from the latest source snapshot? On good teams, there’s a single script you can run that does a full checkout from scratch, rebuilds every line of code, makes the EXEs, in all their various versions, languages, and #ifdef combinations, creates the installation package, and creates the final media — CDROM layout, download website, whatever.

Ask yourself the same question – Can you build your application in one step?

In my current company, to build one of our application for an environment, a programmer has to follow the below steps.

  1. Compile the application.
  2. Open the “App.config” file and change the connection strings and logging details.
  3. Build the setup project to package the application.

The above approach is error prone as programmer may forget to perform some steps or he may enter wrong details into the configuration file. This process is time consuming and you don’t want to do something which a machine can do in a better and accurate way. Thus, it is clear that we need a one click build system which compiles the application, copies necessary configuration information depending on the current build settings and package the application with very less user involvement.

Visual Studio allows programmers to execute custom DOS commands before or after the build. Let us utilize this feature and will see how it can ease our builds. In summary, we will be doing the following steps.

  1. Create separate configuration files for each environments.
  2. Create an empty App.config file.
  3. Write a DOS script which reads the appropriate configuration file and put the contents into App.config file before project is built.

Assume we have two environments, DEV (development environment) and SIT (Software testing group’s integration testing). Figure below shows the configuration settings for DEV and SIT. Since we need release and debug builds for both environments, DEV-DEBUG, DEV-RELEASE, SIT-DEBUG and SIT-RELEASE are created.

Visual Studio's configuration manager

Next step is to create the configuration files for each environment. I have created a separate folder to keep the configuration files. You need to add “App.config” and leave it as blank. You should not modify the “App.config” file directly. Direct updates to the “App.config” file will not be persisted as it will be overwritten on each build.

Here is the screen-shot of the solution explorer.

Solution explorer

Consider the following script.

echo Performing postbuild for $(ProjectName)
IF "$(ConfigurationName)"=="dev-debug" (
copy "$(ProjectDir)Config-Files\dev.config" "$(ProjectDir)App.config"
) ELSE (
IF "$(ConfigurationName)"=="dev-release" (
copy "$(ProjectDir)Config-Files\dev.config"  "$(ProjectDir)App.config"
) ELSE (
IF "$(ConfigurationName)"=="sit-debug" (
copy "$(ProjectDir)Config-Files\sit.config" "$(ProjectDir)App.config"
) ELSE (
IF "$(ConfigurationName)"=="sit-release" (
copy "$(ProjectDir)Config-Files\sit.config"  "$(ProjectDir)App.config"

This is a trivial DOS script. It checks the current configuration and copy the appropriate configuration file to the App.config. All this happens before the project is built.

Visual Studio provides several macros like $(ProjectDir) which can be used to determine the current settings used in the project. For example, $(ProjectDir) macro gives the current project directory. Put the above script in the Pre-Build event command line area in the project properties. While building the project, VS will take this script and execute it. So before the build starts, we will have our App.config file filled with correct configuration details.

This approach works well. But some projects may have sophisticated builds and simple methods like this won’t just work. I would like to hear how you guys are managing such scenarios.

Happy programming!


Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s