Deployment and Updates of Desktop Applications: WiX, ClickOnce and Other Scenarios
Wednesday, July 8, 2009 at 17:28 in
Integration,
management,
xLim As we all know, web applications became quite popular these days. One of the reasons is that they generally do not need any installations in order to be used. Upgrading them is simple, too. When you got new version to roll-out – just update web server and everything below. Users will get new UI automatically. At most you might want to ask them about refreshing their cache.
This simplified deployment routine adds the benefit of reduced development friction, allowing developers to have shorter development cycles in an agile manner. This eventually allows having better feedback loops leading to better products (ceteris paribus).
Desktop applications do not have such flexibility and simplicity. Almost always a development team has to deal with the packaging, deployment and updates in a manual or semi-automated way. This increases development friction.
Let’s take a look at some deployment scenarios in small and medium development projects.
Scenario 1. Project deliverables are produced by running the build, then manually putting its output into a zip file and sending it to the customer. That’s the simplest option one could get. The approach fits scenarios where some non-critical tool with a short life-cycle (i.e.: under a month) is being developed.
This scenario has a hidden cost of high development friction and also high probability of a human error. Although this sounds like something non-important (what could be more complex than zipping a few files, right?), this consistently slows down development and eventually leads to some reputation-hurting mess-up.
Scenario 2. Project deliverables are produced by starting some special build on a continuous integration server. After running a common integration routine, it grabs build outputs, applies certain configuration settings, packages into a nice zip and copies to a well-known distribution location. Usually that’s a product/version folder on a web server (it optionally could be protected by some authentication and exposed to the Internet).
Optionally the build might update common download.html file pointing to the download locations. This way the cost of releasing the product (on developers’ side) is about two mouse clicks and sending notification to customers. Customers still have to download, unzip and update manually.
This scenario works well in situations where the project deliverables are consumed by tech people. For example, Lokad Shared libraries are distributed this way. You can check out the build script for that, if interested.
Scenario 3. This scenario is a slight variation of the previous one and targets non-geeky customers. To make customer experience friendlier we might produce installable package instead of the raw zip archives (deployment process stays similar). So customers will simply have to download the installer and walk through some wizard in order to get the thing running. Additionally, the actual desktop application might have simple update framework capable of checking for the latest deployed version and helping user to download and install it as needed.
Let’s see how this could be implemented in .NET world. There actually are at least two major options.
Option 3.1. First option would work well for simple deployment scenarios. It is called ClickOnce. Basically, this is a Microsoft technology providing simple deploy and update experience. It is tightly integrated into .NET and Visual Studio and hides some complex decisions from the developer.
Advantage of this technology is its simplicity and ability to get started in minutes. Disadvantage is the same one – simplicity and inability to handle more complex scenarios. This makes this technology suitable and efficient only within a specific set of scenarios.
Here’s how the deployment process might work:
- Integration server, in addition to the usual routine, runs ClickOnce publishing tasks exposed by .NET SDK.
- These tasks produce deployment files that could be exposed to the outside world via the web server.
- End-user only knows about some html URL that allows him to either run executable bootstrapper or launch the actual ClickOnce application. Bootstrapper is a Win32 application capable of automatic download and deployment of all the required prerequisites (i.e.: .NET Client Profile).
- User clicks Next a few times, looks at some progress bars (giving him a sense of accomplishment) and then is presented with actual running application.
Another nice feature of ClickOnce is about the way it handles updates. You can configure application deployment in such a manner that at every launch will check deployment server for the new updates (automatically downloading and installing them if needed). Or this could happen once in a week or so.
This simplifies the actual deployment process. If you have customer with an issue and a deployment server, then issue fixing is just a matter of:
- Writing unit test.
- Fixing the issue.
- Committing it to version control repsitory.
- Telling Integration server to perform the deployment after the build.
- Asking customer to restart the application.
Auto-magic will take care of the rest.
Option 3.2. Sometimes ClickOnce is too limiting for the project deployment purposes. Some limitations might show up when you need to:
- share components, folders and files between multiple products;
- configure application to start up with Windows or perform some other complex tasks;
- deploy installations with multiple optional features or do anything that requires user’s input;
- handling upgrades gracefully;
- deploy applications to a large number of machines at once.
In order to handle these tasks we need to give up on the simplicity of ClickOnce and switch to something more powerful. My favorite option at the moment is Windows Installer XML 3.0 by Microsoft (or WiX, for short).
WiX allows creating MSI files by writing some XML-related code, and provides some tools and even Visual Studio integration to make developer’s life easier. Yet, the technology still has a decent learning barrier. Other disadvantages are:
- Programming in XML (even writing complex configurations) is inefficient and error prone by default.
- You can’t unit test your installation (ICE evaluators can offer some help but they fail to run on the integration server sometimes).
Yet at the moment that’s my favorite technology for handling complex scenarios that ClickOnce can’t handle.
If you are interested in some samples, I invite you to have a look at some projects by Lokad. Seeing WiX in action is as simple as:
- Make sure that WiX 3.0 is installed on your machine
- Checkout Call Center Calculator or Safety Stock Calculator (via version control).
- Execute go /t:CreateInstall /p:Version=1.2.3.4 in the root project folder
Sources are made public under the new BSD License.
Here are some additional links on WiX that I found useful while learning the technology:
- Windows Installer Components Introduction
- WiX Wiki.
- WiX tricks and best practices on StackOverflow.
- Deploying additional components with GenerateBootstrapper task.
- How do I start an application after install?
- How do you create an MSI to deploy a VSTO 3.0 Add-in?
- System Folder Properties at MSDN
- From MSI to WiX article series.
Deployment and auto-update process on top of WiX might work like this:

- Integration server, when asked to publish release, does the following:
- It creates a new MSI installer by building the project and then running WiX-related MSBuild tasks. This MSI uses major upgrades to deliver new functionality and update files on user’s computer.
- Updates the download page by redirecting links to the latest package
- Updates custom deployment manifest, which could be as simple as ProductName.Release.txt file containing latest version number
- Copies latest released MSI to ProductName.Release.msi in a well-known location
- When user checks for the updates (or software does it for him) following takes place:
- A simple web request to the version file somewhere over the network will tell if we are up-to-date
- If we are not – just inform the user about that and offer him to perform the upgrade
- When user accepts, close the application and launch ClickOnce bootstrapper bundled into the MSI. Bootstrapper does not actually care about the ClickOnce, it merely checks for the prerequisites, then downloads and installs the MSI it knows about. In our situation this MSI is ProductName.Release.msi.
- Launched MSI is implemented as a major upgrade, so it will simply offer user to click Next a few times (firing off UAC if operating system supports it), perform the upgrade and then re-launch the application
The process of deployment and auto-updates might feel slightly complicated, yet it involves very little coding (except for the MSI creation). The most interesting part is that it has to be done only once. After that fixing issue for the customers is just a matter of:
- Writing unit test
- Fixing the issue
- Committing changes to version control repository
- Telling Integration server to perform the deployment after the build.
- Asking customer to click the "Check for updates" button in his application.
This brings us closer to the Agile development methodologies in the development of desktop applications with complex deployment scenarios.
Related links:
Reader Comments (4)
A great roundup of the available technologies, Rinat.
For builds, I'd highly recommend you take a look out FinalBuilder. We are saving massive amounts of time now we have migrated from MSBuild. We run FinalBuilder under Team Foundation Server and it will fits neatly into any CI scenario - it even has its own build server if you needed one.
For installs, I'm currently looking to move to Tarma Installer - fully featured and very good value for money. Haven't spent enough time to be definite about it, but it fits into a CI environment as it is fully scriptable.
Did I mention I'm allergic to XML ;)
Hi Sean, thanks for the updates.
Re FinalBuilder - I did try this out some time ago, while learning MSBuild and NAnt. As I remember, it was nice, flashy and with nice building blocks. We didn't get along well))
Re allergy to XML - I agree on this one. It adds significantly to the learning barrier.
I've read you're post with great interest, specially the part on using Wix and doing auto-upgrade.
However I don't really understand the part on using the ClickOnce bootstrapper and bundling it into the MSI.
Could you explain what you mean here in a bit more detail?
You are bundling the ClickOnce boorstrapper into the MSI, as I read it inside the MSI of the application to install. But then later you write that the bootstrapper downloads and installs the MSI it knows about: "In our situation this MSI is ProductName.Release.msi" which is the MSI of the application.
This looks like a chicken and egg situation.
Or are you using another MSI for the ClickOnce bootstrapper?
By the way, very interesting blog
Thanx,
Serge
Serge, you are correct, there is a logical dependency in the deployment process that makes it feel slightly awkward.
To make it simple, just ignore words "ClickOnce" and treat the Bootstrapper.exe for what it really is - simple Win32 executable that can check/install prerequisites and then download/install some specific MSI, given its url (which is hard-coded in file).
It helps to deliver the latest MSI (i.e.: when customer does not have .NET or Windows Installer 3.1 and does not know how to install that) and it is included in the MSI to simplify delivery of the latest version (and to avoid hand-coding this logic manually).