Auto Update Desktop Applications

Harshith Gowda
WhatfixEngineeringBlog
6 min readMay 27, 2022
Image by Gerd Altmann from Pixabay

Introduction

Software upgrades are an inevitable part of application development — be it web or desktop. A new feature support or critical bug fixes are made available to the end users through an upgrade. This article aims to describe the challenges, suggested approach and caution to exercise in supporting auto update for desktop applications.

Background / Context

We’ll look at how to update desktop applications in this article. Let’s look at the distinction between a web application and a desktop application before we get into how updates work for desktop applications.

Approaches and Challenges of Application Update: Web vs Desktop

In web applications, the UI is served from where the web app is hosted. So, when a user visits a web application, the user is assured to use the most recent version deployed on the server. If the user is already logged in and using the app, we can ask him / her to reload it by displaying a pop-up message.

For a desktop application, the application’s binaries reside on the user’s computer. So, a new version has to be downloaded and updated on the user’s machine. This update can be triggered either (1) manually or (2) presenting an auto updater along with the software. Let us explore both the approaches in little more detail.

The first approach is to manually download and install the latest version. The control and decision to upgrade is with either the end — users or the IT administration team of an organization. However, the flexibility to decide comes at the cost of increased complexity of logistics and execution, especially in an enterprise setup with a large user base. The intervention and reminders to upgrade also becomes increasingly painful and intrusive if the software has frequent updates / patches.

The second approach is to bundle the auto updater along with the application. The auto updater functions based on version change information.

In the second approach users don’t have to worry about updating their app manually, updater will run in a certain interval of time, check if there is an update available and downloads and updates the app. Which reduces the lot of manual effort and also cost.

Approach for a Desktop Application’s Auto Updater

From the above discussion we learned that adding an updater in the app is feasible and cost effective, so now the question is how to implement the updater.

Pre Requisites

The first step is to create a versioning system for the application so that we can compare the local version to the remote version. We can have a version file which will have the current version of the app which is running on the computer. And we can host one more file on server or CDN which will have the latest version available, and the download path, we will call this file as manifest file here onwards.

We decided on two files: a version file that contains the current version of the app running on the computer and a manifest file that is hosted on CDN and contains the most recent version available as well as the download path. The following step is to create executables and package them. We can package executables as zip files and calculate the hash of the zip file to confirm the package’s integrity. Upload both zip files and files which contain the hash of those zip files to a server or any cloud storage service provider and update the version and the download path in the manifest file.

Approach

When the updater on the user’s machine starts, it has to download the manifest file from the server and compare it to the local file version. To download the manifest file updater has to be aware of the manifest file URL. We can hardcode the base URL in updater code itself and then create an executable file if the URL will be the same for all the users. But let’s say a manifest file is hosted in a different location for different users, then the URL has to be passed to updater from the main app before starting the updater. If necessary, we must whitelist the URL on the user’s PC; otherwise, the download of the manifest file may fail.

After successfully downloading the manifest file and comparing version with local version file, the updater must download the most recent executables if a new version is available. Updater downloads the zip file and file which contains the hash of the zip file using the download path mentioned in the manifest file. To avoid permission issues with the folder, download the zip file inside where the application is installed. Download might fail if required space is not available on the disk. If the download is successful, calculate the hash of the zip file and compare that with the downloaded hash to ensure integrity of zip. If the hash doesn’t match then zip might have corrupted, so delete the downloaded zip file and stop the update, otherwise extract the zip file to the folder.

After successful download and extraction of the zip file, replace the executables. Before replacing the executables, kill the process of the app. If the app is installed and running at user level, the updater should kill the process of the current user. If the processes are killed successfully, replace the executables and restart the application.

Let’s say certain of the application’s executables change frequently while others do not. As a result, we can split executable files into numerous zip files. We can package executables that change frequently in one zip file and executables that don’t change frequently in another zip file, and version them appropriately. This lowers the cost of the CDN and speeds up the update process. However, this adds to the difficulty of keeping the update procedure atomic.

To keep the update process atomic, download the all zip files one after the other and then extract them to the same folder so that we don’t end up partially copying while replacing executables. Stop the update if any one of the downloads, extraction or copy operation fails.

Flow Diagram

Possible Errors

There are numerous errors that can cause the updating process to fail.

  1. If the user’s PC is behind a proxy, the download of the manifest file or zip file may fail; to avoid this, whitelist the URLs where the manifest file and zip file are hosted.
  2. If the user’s PC lacks the necessary storage, the download of the zip file or extraction of the zip file may fail. To avoid this, instruct the user to keep enough disc space.
  3. If the updater does not have the required permissions, the killing process of application may fail. To avoid this make sure updater and application are running with the same user permissions.
  4. Copying the executables may fail if the application is not stopped properly.
  5. Because of the partial copy, restarting the application may fail; to avoid this, make the upgrading process atomic, as we discussed in the previous section.

If the upgrade process fails despite taking care of the above error scenarios, collect the error logs, save them in a logs file for further analysis, delete the downloaded packages and extracted files, restart the application, and gracefully terminate the updater.

Best Practices to Trigger the Upgrader

We saw how to construct an upgrader in the previous part, but now the question is how to start that upgrader.

  1. When a user launches an application, the application can check if a new version is available and display the user the update choice if one is available.
  2. Another method is for the application to initiate the upgrade automatically at a certain interval, such as every hour or once per day.

Drawbacks of Auto Upgrade

The following are some disadvantages of using the second approach to trigger the auto upgrade

  1. If the user is using the application, the upgrader may interrupt.
  2. If the upgrader starts while the user is shutting down the machine, the update will fail.

References

  1. https://stackoverflow.com/questions/7395609/what-is-the-best-way-to-auto-update-a-windows-application
  2. https://www.freecodecamp.org/news/the-architecture-of-an-intelligent-application-update-system-3fc2f27a4a2/

--

--