Fine Grained Versioning with ClickOnce
ClickOnce is a Microsoft technology released with version 2.0 of the .NET framework that allows for easy deployment and updating of .NET windows applications from within Visual Studio. Deployment functions by copying the application files to a file, ftp, or web location along with a manifest. The manifest is an XML file with a .application extension that contains a list of all included files as well as security-related information such as publisher identity. Each time a new version of the ClickOnce app is published, a new subdirectory is created and the updated files are placed there. All deployed versions of the program exist independently, which means that we need only identify the user and point them to the appropriate version of the application to control what version they receive.
First, let's create a simple windows application and deploy it via click-once. Create a new windows application project, put a label on the form, and place some code into the New() sub so we can see what version we have.
label1.Text = "Version: " & _
Now, go to the Signing tab under Project properties, check the 'Sign the ClickOnce manifest' box, and create a test certificate by clicking the 'Create Test Certificate' button and choosing a password.
Now that we have our certificate, we are ready to set up the ClickOnce deployment. Select the Publish tab and enter a publishing location and an installation URL (you can enter these directly or use the Publish Wizard at the bottom). The Publishing location is the physical location where the deployed files will reside. The installation URL is the URL users will use to download and install the application. For our purposes we want the application to be available offline, so select the second radio button under 'Install Mode and Settings'. In order for our versioning to function, the ClickOnce files must be deployed under the folder tree of a web application, so keep this in mind when choosing a deployment location.
Note the update options visible by clicking the 'Updates...' button.
At this point we have a ClickOnce application that is ready to deploy. Once deployed and installed, using the displayed update option settings, the application will check for updates every time it starts.
If a new version is available, the user will be prompted to update.
At this point we have a deployed ClickOnce application and we are ready to implement versioning. This works by setting up a web-based redirect for the master .application file. First, we add the .application extension to IIS's allowed list. This can be done in the Application Configuration section of the Home Directory tab under web site properties in IIS.
Once this is complete, create a new WebApplication and add a Handler class to it.
Then register the handler in the application's web.config file. The format for handler type is [Namespace].[ClassName], [Assembly]
<add verb="GET" path="*.application" type="WebApplication1.MyHandler,WebApplication1"/>
Now, go back to our sample click once app and reopen the Updates dialog under the Publish tab. Enter an update location that will go through the web application.
Finally, modify the http handler we created earlier to return the appropriate version for the request. Here we return a hardcoded version, though naturally a real implementation will handle authentication to provide more flexibility.
The header can be configured in IIS or set in code as shown here.
Words of warning
When using temporary certificates for ClickOnce signing purposes, if the certificate expires and you replace it with a new one, any current installations of your application will be unable to update and all users must reinstall. This is a known bug. Luckily, there is a workaround that allows you to extend the expiration date of the certificate indefinitely. See http://support.microsoft.com/Default.aspx?kbid=925521 for details.
It is important to sync the location of the deployed app manifest with its update location. IIS will not serve up a file that is not present, so your handler will never fire if the update path is invalid.
If you are using Visual Studio 2008, the deployed folder structure is slightly different. The .application files for each version reside in their specific subdirectories instead of in the master folder. This can cause problems if you have a versioning scheme designed under VS 2005, and then deploy the application via VS 2008.