I’ve been working on a Smart Client Software Factory development effort, and as we were nearing the end of the development, I spent some time looking at how I would deploy the client application to end users. Though I was initially attracted to ClickOnce deployment because of the automatic update feature, I shied away from this and ended up crafting an MSI installer. Having tinkered with both technologies, I now understand better when ClickOnce and MSIs are appropriate. In my opinion, ClickOnce should be used only if MSIs cannot be used. I find MSIs provide much more control over the installation process, and from my experience, are somewhat easier to put together when your application is architected around the Composite UI Application Block.
This being said, the installer has to be able to handle the following requirements:
- The same MSI should be used for development, testing, and production. This helps to ensure that the same code base is used throughout all environments.
- The installer should be able to encrypt app.config sections during the installation.
- You should be able to debug into the installer during development.
Now, before I move into the meat of the installer program and the setup project, let’s talk about app.config files and the web references in Visual Studio 2005. When you add a web reference, Visual Studio 2005 performs a number of steps to make it easy to change the web service Url without re-compiling code. One of those steps is to create entries in the app.config file of the project. If the project does not contain an app.config, Visual Studio will create one for you. So what happens to the app.config when the library project get compiled? Well, you end up with a [AssemblyName].dll.config. So your application directory may contain one exe, one exe.config, and nothing else. You might be tempted to copy the dll.config files into the application directory, but that will not achieve the desired result: you want the application to obtain its web service Urls from configuration so you can make changes between environments easily. So here is the trick:
Open the app.config file(s) from the library project(s) and copy the <section name=“YourProjectName.Properties.Settings“ child element of <sectionGroup name=“applicationSettings“…> into the same place in the app.config file of the Windows Forms project. Then, copy the entire content of the <applicationSettings> section from the library project’s app.config into the Windows Forms app.config file, taking care not to replace its contents but add to it. As a result, the app.config of the Windows Forms project will look like this:
<sectionGroup name="applicationSettings" type="System.Configuration.ApplicationSettingsGroup, System, Version=18.104.22.168, Culture=neutral, PublicKeyToken=b77a5c561934e089" >
<section name="YourExeProject.Properties.Settings"… />
<section name=" YourLibraryProject2.Properties.Settings"…/>
<setting name="Timeout" serializeAs="String">
<setting name="Service1" serializeAs="String">
<setting name="Service2" serializeAs="String">
I’ll get into
the code that satisfies the installer requirements on my next post.