ClickOnce Is a Complex XCopy
ClickOnce was designed to make deployment of applications easier. The goal was to allow a user to start using an application without having to install it. Additionally ClickOnce was suppose to allow developers to auto-update their applications without having to write hardly any code. One of the premises of ClickOnce is that you don’t need to be an administrator to use a program. Overall it met these goals. The reality though is that ClickOnce is horribly, horribly out of date for the modern times and yet Microsoft continues to push it as “the” easiest deployment strategy. My recent attempts at using it for a simple client application met with a resounding failure.
Here’s the list of benefits ClickOnce supposedly brings to the table.
- Publish an application to a website or file share
- Does not require administrative privileges to deploy or run
- No setup program needs to be run but an application can still add itself to the Start Menu, Desktop and create an icon in Programs and Features
- Automatically update an application with only a handful lines of code
ClickOnce does all this but unfortunately it is simply too old to be useful in modern .NET applications. Let me identify the areas where I had trouble when I recently tried to use ClickOnce.
Publish Our Way… Or Else
In my particular case I need to be able to control how publishing occurs based upon whether a client has a web server (unlikely) or file server available. Ideally I would like a user to be able to enter a URL into a browser and my application automatically downloads and runs. Think WCF service here. Unfortunately ClickOnce doesn’t support this approach. Even worse is that, unlike almost all of the .NET Framework, it is completely locked down so you can’t even override the implementation. You’re stuck with the publishing options that ClickOnce exposes. Who thought it was a good idea to completely prevent extending ClickOnce? If there is anything we’ve learned over the years it is that developers like to extend things. Here ClickOnce just doesn’t have the flexibility, or extensibility, needed to allow custom publishing options.
No Administrators Here – Ever
One of the important features of ClickOnce is the ability to run an application without administrative privileges. This is important and useful for a lot of applications. However with the advent of Vista and UAC the rules have changed a little. It is now more common to have an administrative application run as a normal application until such time as administrative privileges are needed.
Visual Studio allows you to add an application manifest to your application. The manifest contains a variety of things but on the security side it allows you to specify how you want to support Vista and UAC. On one side is the default setting where UAC kicks in when needed. But on the other side is an option to require administrative privileges automatically without requiring the user to change shortcut settings or anything else crazy like that. Yes there do exist applications that require administrative privileges.
Once again ClickOnce will thwart your efforts. If you have an application manifest with UAC settings in your application then ClickOnce won’t work. Why? I have no idea. It seems that the designers of ClickOnce thought that this requirement meant that an application shouldn’t be allowed to have administrative privileges, ever. Hence if you plan to use a manifest to control UAC then you can’t use ClickOnce.
No Setup Required – Even If It Already Exists
ClickOnce gets this one mostly right. You don’t need to install any files to get a ClickOnce application working. But what if you need to install some additional files. Well then you are going to have to ditch ClickOnce. Sounds like a fair tradeoff but here is one very big gotcha – this includes versions of system binaries that have been around as long as .NET.
Specifically I’m talking about the v6 Common Controls added in Windows XP. To avoid breaking code Microsoft made the decision to make the v6 CCs optional. Most applications would instead target the v5 CCs. Sounded great because it ensured that an application written under XP would run under Windows 2000 without change. Fast forward to today. .NET v4 only supports XP+ so any v4 .NET application can safely use the “new” v6 CCs where all the new Windows controls reside. But if you’re using ClickOnce then you are once again out of luck. The issue is that in order to get the v6 CCs to load properly you have to add them as a dependency in your application manifest (I’ll blog later about this hack). Adding a dependency to the manifest causes the publish process to fail because the publisher assumes you are relying on a binary that isn’t available to ClickOnce (even though it will be there for all versions of Windows).
So, in summary, if you want to use ClickOnce then you are stuck with a pre-XP user interface. Now you might think you can work around this limitation by building your app, publishing it and then editing the post-build manifest but guess what – it won’t work. See ClickOnce doesn’t want you tampering with any files once published so it checksums them. If any file is modified then ClickOnce fails. In order to modify a file you’d have to make the modification and then run a command line tool to regenerate the publish data. Needless to say switching from Visual Studio to the command line to work around a severe limitation in ClickOnce just doesn’t sit well with me.
Autoupdate Your Application – Sometimes
Finally we have autoupdate. Autoupdate sounds like a great idea – push a new version of your application to a website and users can be notified to download it. All this wonderful technology is wrapped in a simple static class you can use from your application, some conditions may apply. These conditions include the fact that the application must have been deployed via ClickOnce to begin with (i.e you can’t install via a CD and then autoupdate). You also cannot be running in the debugger. Do what??? Yes that is right the designers of ClickOnce figured that nobody would be debugging code. If you call the autoupdate code within the debugger you’ll get an exception. The logic of this design alludes me. I’m also confused as to how they could even test it but that is a different story. Nevertheless in order to use autoupdate you have to first verify your app isn’t running in the debugger and you were originally deployed using ClickOnce (they at least provide a method for that check).
I fail to see why either of these requirements is necessary for the proper implementation of updating. No problem, says a developer, .NET is extensible so I’ll just extend the infrastructure. Or not. Again, the designers of ClickOnce felt autoupdate was either too tricky or too special to allow any sort of extensions. The only extending you can do is to rewrite it yourself.
If you felt like I’ve been harsh on ClickOnce you’d be right. I think it is deserved. This isn’t some legacy technology that we’re talking about. It is one of the preferred deployment approaches that .NET recommends and yet it is completely outdated and inflexible. I believed the hype and samples that I saw on ClickOnce so much that I was going to use it in a recent project. Within the first few hours I realized I’d have to either hack my way around ClickOnce or give up on it entirely. So now I have to write my own publishing code and autoupdate code just because ClickOnce is outdated.
Here’s my feature request list for the ClickOnce team.
- ClickOnce has to be extensible. Publishing and updates are the primary areas.
- ClickOnce must support the newer OS features like UAC and v6 Common Controls (and others).
- ClickOnce needs to be fully integrated into Visual Studio without the need to run command line tools for something as common as changing a post-published file.
- Autoupdating needs to work whether I’ve deployed via ClickOnce or via an alternative manner. After all it really just needs to know where to go check for updates.
- ClickOnce has to work within the debugger. If I cannot run Visual Studio then the tool is useless. I shouldn’t have to code around technologies.
I’m hoping that one day ClickOnce will be brought up to snuff with the rest of the framework but for now I consider it no better than the old Visual Studio Setup Projects – good for novices but a complete waste of time for “real” applications.