How to implement auto-updates in C# – Part 3

The easiest way to provide basic auto updates, without having to alter the code of your application is probably ClickOnce

ClickOnce icon

You still have to double-click.

The way it works is simple. All you have to do is to copy the files that your project needs to run (executable, dlls, configs etc) to a folder accessible from your end users along with 2 files, an application manifest and a deployment manifest. You can use a shared folder if your deployment is within a corporate environment or a web server for a broader audience.

All your users need in order to install your software is a link to the deployment manifest file, with the extension .application, and to have .Net already installed on their machines. After that first installation ClickOnce will check the deployment location and if there is a new version it will interact with the user in order to install it.

Of course you don’t want to do all these steps manually every time you make an update to your code. That’s what we have a build server for, right?

How to create the manifests

The easiest way I found to automatically generate the manifests was with the use of Mage.exe, a command line tool provided by Microsoft specifically for that purpose.

The first thing you need to do is to create a new build configuration for the deployment of your project. Add the necessary build steps to build a release version of your application and to run all the unit and integration tests.  Then add two more steps: one to create the application manifest and one to create the deployment. Both steps need to execute mage.exe with the appropriate command line arguments for each manifest file.

An example for the application manifest on TeamCity would look like this:

Step 3: Create application manifest

Runner type: Command Line (Simple command execution)
Working directory: same as checkout directory
Command executable: “C:\Program Files (x86)\Microsoft SDKs\Windows\v8.0A\bin\NETFX 4.0 Tools\Mage.exe”
Command parameters: -New Application -toFile .\MyProject\bin\Release\MyProject.exe.manifest -Name “MyProject” -Publisher “CompanyName” -UseManifestForTrust t -Version %build.number% -FromDirectory .\MyProject\bin\Release

 

And for the deployment manifest:

Step 4: Create deployment manifest

Runner type: Command Line (Simple command execution)
Working directory: same as checkout directory
Command executable: “C:\Program Files (x86)\Microsoft SDKs\Windows\v8.0A\bin\NETFX 4.0 Tools\Mage.exe”
Command parameters: -New Deployment -toFile .\MyProject\bin\Release\MyProject.application -Install true -Name “MyProject” -Publisher “CompanyName” -ProviderUrl “http://companyurl.com/download/MyProject.application” -AppManifest .\MyProject\bin\Release\MyProject.exe.manifest -Version %build.number%

 

The ProviderUrl can be a shared folder instead of a URL like the one above as long as your users have access to it. Installation of an application is supported over file://, http:// and https:// protocols.

Note that we use TeamCity’s variable %build.number% as the product’s version. By formating the build version of this build configuration to something like:

Build number format: 1.0.0.{0}

We can ensure that the version is auto incremented every time we run this build.

How to copy the files to the deployment location

This is the easy part. All we need to do at this stage is to add a last step that will copy those files to the appropriate location accessible by the ProviderUrl mentioned above. If that is a shared folder all we need is to use the copy command passing the from and to directories. Make sure you copy everything from the Release folder that was included in the application manifest.

Here is an example of that last step where we have to copy our files to a remote linux server using PuTTY secure copy:

Step 7: Copy release files to server

Runner type: Command Line (Simple command execution)
Working directory: same as checkout directory
Command executable: c:\Program Files (x86)\PuTTY\pscp.exe
Command parameters: -batch -i “C:\Path\To\Encrypted\Key\encrypted_key.ppk” MyProject/bin/Release/*.* deploymentuser@server.url:/var/www/download/

 

And that’s it! You now have implemented auto-updates for your application!

Complicating things

So far we have seen how easy it is to setup auto-updates with ClickOnce. Once you start using it though you will soon find out that there are a few complications down the line that may or may not affect you depending on the auto-update requirements of your application. In any case it is better to consider a few things in advance.

Decide the right update-strategy

ClickOnce will check for updates of your application in predefined instances like before the application starts, after it starts and in specified intervals. If a new version is found it will ask the user whether it should install the new version or not.

This approach is sufficient when your updates are optional. However it becomes trickier to enforce important updates, like security fixes, breaking changes to remote APIs etc. The only way you can achieve that is to require ClickOnce to check for updates before the application starts and mark each update as necessary by specifying a minimum required version in the deployment manifest. Here is an example of a build-step in TeamCity that adds that requirement to the manifest which was created in a previous step:

Step 5: Force update – deployment manifest

Runner type: Command Line (Simple command execution)
Working directory: same as checkout directory
Command executable: “C:\Program Files (x86)\Microsoft SDKs\Windows\v8.0A\bin\NETFX 4.0 Tools\Mage.exe”
Command parameters:-Update .\MyProject\bin\Release\MyProject.application -MinVersion %build.number%

 

In this example the minimum required version is the version we just built, as defined by the %build.number% variable, forcing ClickOnce to install it the next time it checks for updates.

For more information see how to choose your update strategy.

Make sure all prerequisites are installed

ClickOnce is part of .NET, therefore if .NET is not already on your user’s machine, your user can not install your application either. Remember that the MyProject.application file is just an xml manifest. Without ClickOnce your user’s machine can not make any sense of it. But even if there is a version of .Net already installed you need to make sure that it is  one your application is compatible with.

To address this issue you can provide an additional setup.exe file which will install all the prerequisites of your application, like .NET for example, and then use the manifest to install the application itself. This file is called a “bootstrapper” and you can automate the creation of it using MSBuild tasks. You can find more information in how to generate a bootstrapper task and how to create bootstrapper packages.

Server and Client issues

As we mentioned already, ClickOnce applications can be distributed over http by providing a web page with a link to the deployment manifest file, the one with the descriptive extension application”. The end users just need to click (once) on the link and .NET runtime will get them through the installation process.

However that behaviour is available only if the link is accessed using Firefox with a special Microsoft add-on installed or IExplorer. In any other case the end user just gets a prompt to download the file instead at best or a new web page with the xml content of the file at worst. To avoid the later you need to make sure you have setup the server correctly to include the relevant mime types for .application and .manifest extensions.

Make sure you review all the configuration issues you might have when you setup your server.

You also might want to consider checking the available .NET version on your user machine and provide a link to either the .application file or the setup.exe that we mentioned earlier. This is not as trivial as it might seem though (see a discussion on StackOverflow).

Sign your deployments and more

Every time a user is trying to install your ClickOnce application will get a warning that your application is not signed (therefore not safe in the eyes of your users). This can be ignored when the deployment is within the same organization but is a serious concern when the application is distributed over the Internet for example.

To avoid that you will have to purchase a certificate and add yet another step to sign each deployment manifest. Here are the sign command options for the Mage.exe tool.

But if you are considering using ClickOnce to deploy and auto-update a commercial application over the Internet you should also check the security implications of deploying a trusted application.

Conclusion

ClickOnce is an easy way to introduce auto-updates to your application but has some limitations. If your requirements allow you to operate within those limitations then you need to look no further. Otherwise you might need to consider an alternative approach that we will discuss at the next part

<Part 2

This entry was posted in How to implement auto-updates in C# and tagged , , . Bookmark the permalink.