3 Comments

We have a .NET-application which support two different versions of IBM WebSphere MQ. At the moment this means that we have to compile two versions of our solution: one with a support for the older 5.3 version and one for the newer 7.0 version. Changing the version isn’t very hard: We just open the project’s properties in Visual Studio and change the file reference to point to the correct external assembly. But doing this 15 times a day is still too much, and more so when considering that we would like to use TeamCity to do the builds for us. Luckily there’s a way to to automate the process by using different build configurations.

Note. You can use the same process if you have to change the project references based on the solution platform (x86 vs x64).

Sample applicationproject_ref1

Let’s create a sample application which demonstrates on how to change the project’s file references based on the build configuration.  The sample application has one button which will report the version of an external assembly when clicked.

The code looks like the following:

   1: private void button1_Click(object sender, EventArgs e)
   2: {
   3:     var testClass = new MyTestClass();
   4:
   5:     var message = string.Format("Version {0} of external assembly", testClass.MyVersion());
   6:
   7:     MessageBox.Show(message, "Information", MessageBoxButtons.OK);
   8: }

MyTestClass is located in an external assembly called testLibrary.dll. We have two different version of it: 1.0 and 1.5. By default we’re using the 1.5 version but in some cases our application should reference the 1.0 version. MyTestClass.MyVersion checks the version of the assembly and reports it back to the caller:

   1: public string MyVersion()
   2: {
   3:     return this.GetType().Assembly.GetName().Version.ToString();
   4: }

When a user clicks the “I’m using” button, the version is printed on a message box:

project_ref2

Creating a new build configuration

We want to automate the process of switching the referenced assembly and this can be done by creating a new build configuration for the sample application. You can do this through the Configuration Manager. By default all the applications have a build configuration for the debug and release versions. Our application also has a configuration called WithV1.0.

config_manager

Project references

By default our sample application references the testLibrary.dll inside the libv1.5-folder.

v1.5ref

We want to change this if the WithV1.0 is selected. This can be achieved by manually editing the project file.

Editing the project file

In order to achieve our goal, we have to manually edit the project file by using our favorite text editor. Inside the file you can find all the project’s build configurations as a xml format. Here’s how the Release and WithV1.0 configurations look like:

&lt;PropertyGroup Condition=<span style="color: #006080">" '$(Configuration)|$(Platform)' == 'Release|x86' "</span>&gt;

  <PlatformTarget>x86</PlatformTarget>

  <DebugType>pdbonly</DebugType>

  &lt;Optimize&gt;<span style="color: #0000ff">true</span>&lt;/Optimize&gt;

  <OutputPath>binRelease</OutputPath>

  <DefineConstants>TRACE</DefineConstants>

  <ErrorReport>prompt</ErrorReport>

  <WarningLevel>4</WarningLevel>

</PropertyGroup>

&lt;PropertyGroup Condition=<span style="color: #006080">"'$(Configuration)|$(Platform)' == 'WithV1.0|x86'"</span>&gt;

  <OutputPath>binx86WithV1.0</OutputPath>

</PropertyGroup>

And here’s how our project’s external references are presented:

&lt;Reference Include=<span style="color: #006080">"System.Windows.Forms"</span> /&gt;

&lt;Reference Include=<span style="color: #006080">"System.Xml"</span> /&gt;

&lt;Reference Include=<span style="color: #006080">"testLibrary"</span>&gt;

  <HintPath>..libv1.5testLibrary.dll</HintPath>

</Reference>

The trick is to make the testLibrary’s HintPath to change based on the selected build configuration. This can be achieved by creating a new property inside all the build configuration sections. The name of the property doesn’t matter but it should be something meaningful. We will use TestLibraryPath in our example:

<TestLibraryPath>..libv1.5testLibrary.dll</TestLibraryPath>

And then we just have to change the HintPath to read it’s value from the property:

&lt;Reference Include=<span style="color: #006080">"testLibrary"</span>&gt;

  <HintPath>$(TestLibraryPath)</HintPath>

</Reference>

After these changes our project file looks like this:

&lt;PropertyGroup Condition=<span style="color: #006080">" '$(Configuration)|$(Platform)' == 'Release|x86' "</span>&gt;

  <PlatformTarget>x86</PlatformTarget>

  <DebugType>pdbonly</DebugType>

  &lt;Optimize&gt;<span style="color: #0000ff">true</span>&lt;/Optimize&gt;

  <OutputPath>binRelease</OutputPath>

  <DefineConstants>TRACE</DefineConstants>

  <ErrorReport>prompt</ErrorReport>

  <WarningLevel>4</WarningLevel>

  <TestLibraryPath>..libv1.5testLibrary.dll</TestLibraryPath>

</PropertyGroup>

&lt;PropertyGroup Condition=<span style="color: #006080">"'$(Configuration)|$(Platform)' == 'WithV1.0|x86'"</span>&gt;

  <OutputPath>binx86WithV1.0</OutputPath>

  <TestLibraryPath>..libv1.0testLibrary.dll</TestLibraryPath>

</PropertyGroup>

<ItemGroup>

  &lt;Reference Include=<span style="color: #006080">"System.Windows.Forms"</span> /&gt;

  &lt;Reference Include=<span style="color: #006080">"System.Xml"</span> /&gt;

  &lt;Reference Include=<span style="color: #006080">"testLibrary"</span>&gt;

    <HintPath>$(TestLibraryPath)</HintPath>

  </Reference>

</ItemGroup>

After saving the project file and reopening it inside the Visual Studio, you can change the build configuration and the application will be compiled against the correct testLibrary.dll. Please note that the Visual Studio UI will not update reference’s information correctly when switching between the build configurations. But you will get the correct results when compiling your application.

v1.0ref

Alternative methods

There’s some other ways to do this but they also require one to manually edit the project files. One way is to specify conditions to PropertyGroup-sections. This StackOverflow question highlights the use of conditions.

Conclusion

Making the Visual Studio to change the project’s references based on the build configuration isn’t as straightforward as it should be. Fortunately it’s easy to go around this problem with a help of a text editor.

You can download the sample application from GitHub.