Can I force the installer project to use the .config file from the built solution instead of the original one?

recursive picture recursive · Jul 26, 2011 · Viewed 7.7k times · Source

I am using the solution to this question in order to apply configuration changes to App.config in a Winforms project. I also have an installer project for the project that creates an installable *.msi file. The problem is, the config file bundled in the installers is the original, un-transformed config file. So we're not getting the production connection strings in the production installer even though the config file for the built winforms project has all the correct transformations applied.

Is there any way to force the installer project to use the output of project build?

Answer

Miguel Angelo picture Miguel Angelo · Aug 2, 2011

First of all: it is impossible to make the Setup Project point to another app.config file by using the Primary output option. So my solution is going to be a work around. I hope you find it useful in your situation.

Overview:

The basic idea is:

  • Remove the forced app.config from the Setup Project;
  • Add a file pointing to the app.config, manually;
  • Use MSBuild to get into the vdproj file, and change it to match the real output of the transformed app.config.

Some drawbacks are:

  • The setup project only gets updated, if the project it deploys build. ahhh... not a real drawback!
  • You need MSBuild 4.0... this can also be worked around!
  • Need a custom Task, called FileUpdate... it is open source and has installer.

Lets Work:

1) Go to your Setup Project, and select the Primary Output object, right click and go to Properties. There you will find the Exclude Filter... add a filter for *.config, so it will remove the hard-coded app.config.

2) Right click your Setup Project in the Solution Explorer -> Add -> File... select any file that ends with .config.

3) Download MSBuild Community Tasks Project, I recomend the msi installer.

4) Unload your project (the csproj) and replace the code from the other question with this one:

Code:

  <UsingTask TaskName="TransformXml" AssemblyFile="$(MSBuildExtensionsPath)\Microsoft\VisualStudio\v10.0\Web\Microsoft.Web.Publishing.Tasks.dll" />
  <Import Project="$(MSBuildExtensionsPath)\MSBuildCommunityTasks\MSBuild.Community.Tasks.Targets" />
  <Target Name="AfterCompile" Condition="exists('app.$(Configuration).config')">
    <!-- Generate transformed app config in the intermediate directory -->
    <TransformXml Source="app.config" Destination="$(IntermediateOutputPath)$(TargetFileName).config" Transform="app.$(Configuration).config" />
    <!-- Force build process to use the transformed configuration file from now on. -->
    <ItemGroup>
      <AppConfigWithTargetPath Remove="app.config" />
      <AppConfigWithTargetPath Include="$(IntermediateOutputPath)$(TargetFileName).config">
        <TargetPath>$(TargetFileName).config</TargetPath>
      </AppConfigWithTargetPath>
    </ItemGroup>
    <PropertyGroup>
      <SetupProjectPath>$(MSBuildProjectDirectory)\$(IntermediateOutputPath)$(TargetFileName).config</SetupProjectPath>
    </PropertyGroup>
    <!-- Change the following so that this Task can find your vdproj file -->
    <FileUpdate Files="$(MSBuildProjectDirectory)\..\Setup1\Setup1.vdproj"
                    Regex="(.SourcePath. = .8:).*\.config(.)"
                    ReplacementText="$1$(SetupProjectPath.Replace(`\`,`\\`))$2" />
    <FileUpdate Files="$(MSBuildProjectDirectory)\..\Setup1\Setup1.vdproj"
                    Regex="(.TargetName. = .8:).*\.config(.)"
                    ReplacementText="$1$(TargetFileName).config$2" />
  </Target>

5) The previous code must be changed, so that it can find your vdproj file. I have placed a comment in the code, indicating where you need to make the change.

Now, everytime you build your main project, the MSBuild will change the Setup project, so that it uses the correct app.config file. It may have drawbacks, but this solution can be polished and become better. If you need leave a comment, and I'll try to respond ASAP.

Resources I Used

MSBuild 4.0 is needed because I need to use String's Replace function, to replace single "\" to double "\" in the path. See MSBuild Property Functions for details about using function in MSBuild.

I learned about the FileUpdate Task in this other question. The official project is MSBuild Community Tasks Project.

These two topics were important to my findings:

Trying to include configuration specific app.config files in a setup project

Problems with setup project - am I thick?