Tricks with app.config and ClickOnce deployment (Saurabh Bhatia)

  • Comments 7
Storing settings in the config File

The app.config file is used for many purposes and one of common uses is for storing application settings like connection strings. For example, you can store a string to the web service reference used by your application in the app.config file.

The idea behind storing the string in the app.config is that you could simply replace the file and change the value of the string. Thus, if you change the web service URL, you could simply replace the app.config and pick up the new URL without recompiling your application.

This is also useful in scenarios where you have a test or development environment where you test your application in a controlled environment before deploying it to a production environment where it connects to a live server. For the development environment, the web service could be running on http://localhost. However when you go live, it could be on a machine like http://mysite.com/

 

Deploying through ClickOnce

Typically, it should be easy to swap out the config file such and replace the string value with the one for the live site when you are deploying to a live environment. However, things get interesting if you are using ClickOnce to deploy your application.

ClickOnce uses manifests that contain hashes to all the files that are being deployed as part of the application. If you change any of the files, the hashes would break and the installation is stopped. So replacing the file after you have published the solution and generated ClickOnce manifests does not succeed. If you replace a file, you must also update the ClickOnce manifests to point to the updated version of the file and re-sign both manifests. This is true for any scenario where you change a file that is going to be published.

 

Updating the app.config manually

You can manually change the app.config file and then update the manifests with the new hash. Then, you must re-sign the manifests before re-publishing your ClickOnce application or solution. The updating and re-signing process for the ClickOnce manifests are explained in more detail here in this post.

One benefit of this option is that an IT administrator can use this process to update a ClickOnce solution without using Visual Studio.

Updating the app.config by using the the Settings Designer

An alternative to doing the file replacement after publishing is to change the file before the publishing step in Visual Studio. This ensures that the correct file gets picked up when you are generating the manifest in the first place. The most obvious manual way to do this is to change the setting value in the Settings Designer, which in turn updates the app.config with the string value for the production environment.

Updating the app.config by using build configurations

There are some tricks you could use so that a different file with the values to the production server get picked up during publish.

You can have two separate config files one for local deployment/debugging and one for a real published or production version of the application. The debugging config file could point to the localhost server whereas the real published config file could point to the real server. You can then configure the build configurations such that the appropriate config file is picked up depending on the Active build configuration.

To add two different app.config files to the project, you can update the reference to app.config in your project file. The app.config is defined in the project file (vbproj or csproj) with the following xml:

<ItemGroup>

<None Include="app.config" />

</ItemGroup>

There may be other nodes in the ItemGroup along with the app.config node. Delete the just app.config from this ItemGroup node and create a new ItemGroup under the <Project> node with the following xml:

  <ItemGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">

    <None Include="app.config" />

  </ItemGroup>

  <ItemGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">

    <None Include="published\app.config" />

  </ItemGroup>

This basically means that the regular app.config file will be used when the Active configuration is set to Debug and the modified app.config with the real production variables stored in the “published\” subfolder of the project is used when the active configuration is set to “Release”.

You can change the ItemGroup conditions to match other build configurations that you may have defined. One possibility is to have a separate “Publish” configuration defined based on the “Release” configuration but only used when you are actually going to publish an application. 

An additional disclaimer with this process is that the VS project system itself and the designers are not aware of the additional app.config file; Visual Studio is only aware of the original file. The modified app.config with values for a production environment is only used by the msbuild process. So if you update the main app.config through the Settings Designer, the modified app.config will not be updated and you have to manually update the file.

Once you have configured your project appropriately you can simply switch between the different build configurations to change the config file and publish the application from Visual Studio without having to go through the update and re-sign process.

Conclusion

ClickOnce uses hashes to detect changes in the files (including the app.config file), and the hashes are stored in the manifests. If you need to update a ClickOnce application and the app.config file to say change a web service URL while moving from a test server to a production server, you can use three different ways to update the manifests and app.config file.

1. Manually edit the manifests to point to the app.config file and update the hash. Then, re-sign the manifests.

2. Use the Settings Designer to select the correct app.config file and republish the solution by using Visual Studio.

3. Create a build configuration for each app.config file and include the correct app.config file.

Leave a Comment
  • Please add 3 and 2 and type the answer here:
  • Post
  • Does this refer only to Visual Studio 2010?  I cannot get this to work correctly with 2008.  The APPNAME.dll.deploy binary continues to have a reference that is not from the correct app.config, though APPNAME.dll.config.deploy is correct.  The config file seems to get ignored when running.  Thoughts?

  • The conditional <ItemGroups> worked out great!  Very Helpful - Thanks!

  • hi, in my case, VS2010 I needed to change

    Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' "

    to

    Condition=" '$(Configuration)|$(Platform)' == 'Debug|x86' "

    and

    Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' "

    to

    Condition=" '$(Configuration)|$(Platform)' == 'Release|x86' "

    it didn't work with the previous conditions and then I looked at the conditions defined by visual studio and copy them.

  • this is the EXACT reason microsoft sucks...

    you cant' chagnge a config file :) .. nice

  • Hi Saurabh,

    Basically I wanted to do the same thing which you explained but scenario here is bit different,

    We have developed a click-once application which has Access database at back-end, this application is installed in about 30-40 laptops already.

    Now, We update our database every day and I upload this Access database to our website and users who are using this application simply click on button which provided in application and It will replace the database which they currently using with the NEW database which I have uploaded on website.

    But If we update application it self and upload that new version of application on website, user will get message box at start of the application that new updates are available and when they try to update , It comes up with error message that "database_name.mdb has different hash value" and it won't allow to update application.

    Now I know when replace database with new database, I have to update Manifest as well but I dont know how to update manifest of already installed clickonce application.

    Any help please ??

    Thanks

  • Hi, Saurabh,

    How include this tag? ( maybe in the file app.config?, command Pre-Build?)

    <ItemGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">

       <None Include="app.config" />

     </ItemGroup>

     <ItemGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">

       <None Include="published\app.config" />

     </ItemGroup>

    I have this problem after publish an new version. The file app.config changed the settings user specific for each build

    Thanks

  • Hello,

    I am having problems when using this approach and trying to use the new "AutoGenerateBindingRedirects" property - go.microsoft.com/fwlink  - I get a nasty error about  Multiple items cannot be passed into a parameter of type "Microsoft.Build.Framework.ITaskItem".

    Any ideas?

    Adrian

Page 1 of 1 (7 items)

Tricks with app.config and ClickOnce deployment (Saurabh Bhatia)