ClickOnce applications are a great way to deliver applications over the internet without actually installing the application on the client's machine. However, getting ClickOnce applications to deploy and update present their own challenges, especially if you cannot rely on using the Visual Studio IDE to publish your application.
The VS IDE will publish a ClickOnce application for you; however, a lot of people cannot rely on this because they have to use command line tools in order to automatically deploy applications in production environments. Unfortunately, the command line MSBUILD utility is not yet capable of publishing a ClickOnce application. The only other way to publish is using the Mage utility. However, at the time this article was written, the command line version is missing some key functionality, and the documentation provided by Microsoft is woefully lacking. This working example is the result of many hours of research by myself and several Microsoft engineers. I hope it helps you get a jump start on deploying your applications.
The attached zip file contains a solution with two projects. MyApp is a ClickOnce application which is intended to be launched only from a website. The application is never actually installed on the client's machine (well, not really, but I'll talk about that in a bit). The idea is that your application must be launched from a web browser. Why would you want to do this? Suppose you want to let your client run an application that communicates with services or databases over the internet. If they have already authenticated from your website, you can prevent the user from having to authenticate in the ClickOnce application again by launching the application directly from your website. GotoMeeting by Citrix does exactly this, and it also happens to be a ClickOnce application as well. MyWebSite is a simple ASP.NET project used to host MyApp.
A problem some people will find with ClickOnce applications is updating a previously installed ClickOnce application. Wait a second; didn’t I just get finished with saying that ClickOnce applications weren’t installed on a client’s machine? The truth is “online only” applications are cached so you don’t have to download the application each time. The cache location is inside of the user's AppData folder, typically something like:
You can muck around in here to find what ClickOnce applications are stored here, but it is usually safe to delete the contents of this directory to clear the cache.
As I said before, the other problem is the Mage command line utility itself. It is missing an option to map file extensions, and another option allows your application to accept URL parameters. I’m hoping Microsoft corrects these deficiencies in a future release of Mage.
I’m not going to delve into the details about these “missing” options, but will explain how I got around the problem. In order to deploy a ClickOnce application, you create a manifest file which lists the files needed and the file to launch the application itself. To complicate matters further, you must sign each of the files with a certificate key. The problem I found with using the command line version of Mage is that when it creates the application launch file (in my demo, called MyApp.application), it is missing some settings. Since the file is just an XML document, I used some batch file commands with a DOS version of the Unix command SED to add those missing pieces. After this file is modified, a ".deploy" extension is added to all of the files to be distributed except the application file and the manifest. If this step is not performed, then any supporting files such as DLLs or icons won't be downloaded and your program won't start. After all this is done, the application file is signed with the certificate, and then the files are ready to be delivered.
Using the code
While my demo is ready to go, if you are building your own ClickOnce application from scratch, make sure that you check the "Enable ClickOnce Security Settings" box Security tab of the project properties. Failure to do so will prevent your application from running on the client machine.
To run the demo is pretty simple. Start a VS command prompt (or make sure you have the paths to msbuild.exe and mage.exe in your environment path). Compile the solution using the build.bat file. You can also start the ClickOnceDemo.sln solution file and build from there if you wish, but I personally wanted a 100% command line way of building and publishing. Next, run the CreateClickOnce.bat file and provide the version # of the application using four significant digits (#.#.#.#) and a name for your website. This second parameter is not really needed, but I added it because you may wish to have the same application used in different versions of your website. Since you can only have one instance of an application on a client machine at one time, you can get around this by changing the name used. Poke around in the batch file if you want to see how this works.
It is important to note that you need to increment the version number each time you call this batch, or else the ClickOnce installer will think it already has the latest version and not download the update. I use other code and applications like FinalBuilder in an automatic environment.
To build and run the demo requires running two batch files as shown below. Note that the CreateClickOnce batch file does all the “Mage magic” as well as uses the SED command (also included). It also copies all the ClickOnce files to the MyWebSite\published directory.
C:\ClickOnceDemo>CreateClickOnce 184.108.40.206 Test
Either run MyWebSite from the IDE, or create a virtual directory pointing to that directory and browse to it. Launch the ClickOnce application by pressing the button. Change the parameters and try it again.
Now, open the solution in the IDE and add a new button to the ClickOnce application and save the files. Run the two batch files again and then test. If your changes don’t appear, you probably forgot to increment the version number when calling CreateClickOnce. If you used 220.127.116.11 the first time you called it, try calling it again with 18.104.22.168 and your updated application should run.
- 8/29/2009 – Initial release.