lickOnce is a powerful and easy-to-use deployment technology that offers a relatively hassle-free experience for end users, when properly configured. Unfortunately, the developer story for ClickOnce varies from super simple to maddeningly complicated, depending on what you are trying to accomplish.
I recently wrapped up a project where ClickOnce was a large part of the release strategy, and also responsible for a lot of the headaches that went with it. When you use ClickOnce as it was intended, it's remarkably effective. But knowing that most of you reading this article probably don't use stuff "as intended," I'd like to offer you the benefit of my experience:
- ClickOnce is a "non-impactful" deployment mechanism. This means you can't do things ordinary installers can, such as adding a new font, putting files in the GAC, or changing registry settings.
Keep this between us, but you actually can
install a new font. It just requires a small workaround. The trick is to make your new font a pre-requisite of the ClickOnce app you are installing, and create a bootstrapper for it. You can do this by creating a setup project in Visual Studio that adds only your font. Then, run the Bootstrapper Manifest Generator found in the MSDN Code Gallery
. After creating this, drop it in the bootstrappers
folder, which—depending on whether you are running VS2005 or VS2008, respectively—looks either like this:
C:\Program Files\Microsoft Visual Studio 8\
Or like this:
C:\Program Files\Microsoft SDKs\Windows\
After you add the bootstrapper, select it as a requirement in your project on the Publish tab.
- ClickOnce applications are installed per user, per machine. If five people use the same machine, each of them will get a new and separate install—and not necessarily all the same version.
There's not much (anything) you can do about the multiple installs, unless you make your application web-only, but you can at least guarantee that they are all running the same version. The trick here is a two-parter: You need to make sure your application checks for updates prior
to running, and you need to set the minimum required version to your current build. Fortunately, you'll find both settings in the Application Updates dialog in Visual Studio.
- ClickOnce isn't exactly what I would call "Environmentally Friendly." By that, I mean if you're like most developer shops, your applications go through a series of environments (DEV, QA, maybe even UAT) before landing in production. ClickOnce doesn't move gracefully between these environments.
Often, moving an application from one environment to the next means you have to tweak the various config files. Database connection strings and web service URLs are just a couple examples of what can change between environments. If you make changes to your config files after the publish step, you need to re-sign them using Mage.exe
and a signed key file.
- Along these same lines, if you want to take the environment scenario to the logical conclusion, and have ClickOnce pull updates from different servers (such as DEV, QA, etc
) then you have another problem. There's no obvious way to re-point a ClickOnce-published build to a new update URL. Mage.exe and MageUI.exe don't provide this functionality.
Fortunately, you can change this without rebuilding and republishing your application. The setup.exe
file that is generated by the publish process has some command line options as well. Typing setup /?
at the command line reveals the /url
switch, which you can use to change the update location that Visual Studio bakes into the setup.exe
file. ClickOnce checks this URL for application updates. Use this with caution, because you aren't just changing the target for the immediate run, but actually modifying the setup.exe
- ClickOnce is a control freak by design. Most of the time, this is a good thing because it prevents people from maliciously tampering with your application after it has been published or deployed. Unfortunately, if your application has user-adjustable options stored in the config file, then you're in for some heartache. ClickOnce applications won't run if any files in the manifest have changed, even after deployment.
You have only one option here—to change your application so it doesn't rely on config file settings. Changing your application to eliminate the config file dependency is really the only choice if you want to use ClickOnce.
- Mage.exe(Manifest Generator, a command line tool) and MageUI.exe (Mage with GUI interface) were not created equally. There are things you can do in MageUI.exe that you simply cannot do in the command line version. Unfortunately, this makes automating the build and publish process pretty tough.
For example, if you need to add a file (or group of files) to your published application as the result of a secondary build process, you'll need to regenerate and resign the manifest. In MageUI.exe
this is a pretty trivial task, although it does require manual intervention. But Mage.exe
has no equivalent functionality, so scripting the process is impossible.
- You publish ClickOnce applications and updates by posting them to the web (or file share). However, there's no method or model to control who can download the updates, or when.
If you have a large number of users, or bandwidth concerns, then you could be in for some difficulty when you post a new version of your application when 9:00 AM rolls around the next day, and 2000+ people try to download the new files at the same time.
- ClickOnce downloads only the files that have changed since the last download. Sounds good, right? Unfortunately that determination gets made by the build version of the file, not any hash or checksum value.
Some shops re-version all files with each build, even if nothing has changed. While the merits of this practice are debatable, it does happen. But if you're using ClickOnce to deploy your application, re-versioning all files means that every change, however slight, results in users having to download the full application payload, making scenarios such as #7 even more unpleasant.
I hope these tips and hints have illustrated what ClickOnce is—and is not—capable of, and help make your ClickOnce experience a little less frustrating.
|Editor's Note: This article was first published in the January/February 2009 issue of CoDe Magazine, and is reprinted here by permission.|