Keeping Windows Applications Up-To-Date via Auto-Updates
Related Programming Articles
Keeping Windows Applications Up-To-Date via Auto-Updates
As a developer of commercial Windows and .Net applications and components, one problem I've had to grapple with on many occasions is how to automatically distribute patches or updates for applications or components we sell. Our goal was to update-enable applications we develop, allowing them to poll for and, optionally, automatically apply designated patches or updates.
In this article, I outline some of the options for creating auto-update applications and describe, in detail, the approach we finally took.
Overview
Our solution needed to be easy to implement on the client side, but also flexible enough to allow us to perform update-related activities that could potentially perform unusual tasks specific to the application. It should provide simple, 'native' support for typical update activities; like installing updated files or assemblies, adjusting registry entries, or launching a downloaded executable (It should support the ability to launch software installers built by Visual Studio or other installer creation tools). Ideally the solution would also support customized, application-specific tasks - starting or stopping services, for example. Also, it would need to be a component that we can easily embed in our end-user applications and utilities, although it would also be nice to be able to deploy the solution as a stand-alone 'agent' which runs independently of our applications.
We wanted our solution to be robust enough to allow us to customize the behavior and UI of the update process with minimal effort. Some examples of customization features we were interested in included:
-
The ability to enable end-users of an application using this update component to do things like manually check for updates via a button or menu option
-
Control over whether the update check, download, and application process happen transparently, or prompt the user first
-
The ability to override UI elements like prompt and progress forms and indicators with customized versions providing custom look-and-feel
Since we can't predict where our applications (or applications incorporating our components) will be deployed, we want the communication between the client and the server to be over the HTTP protocol - ensuring maximum compatibility with secure, fire-walled environments. Furthermore, end-users of these update-enabled applications will essentially be 'anonymous' to us - we don't necessarily know anything about the network environment where our app lives. The process should therefore be client-driven - the agent should poll for updates then request them if any are available.
Finally, the solutions needed to be relatively inexpensive.
To Build or not to Build
I began by looking at the commercial and open-source solutions. While a number of commercial products are available, I found that many of them tended to be strongly focused on managing the desktop in an Enterprise environment. Features like the ability to inventory the desktop, compliance and vulnerability management, the ability to push software packages to named sets of machines, and robust reporting are all valuable for administrators of internal networks, but are overkill for our use-case. We just wanted a simple, embeddable agent which polls for updates for the specific apps it's embedded in.
There are some commercial solutions which are more focused on update-enabling specific apps, but they tend to be complicated to implement, not very customizable, not embeddable, or not .NET-friendly. The commercial products also tend to be moderately to prohibitively expensive.
Open source solutions seem to be completely lacking for this use-case on the .NET platform. A notable exception is 'sample' application available from Microsoft's .NET Framework Windows Forms website. The .Net Application Updater Component described there (and available for download) seemed to be closer to what I was looking for in terms of a simple, lightweight component which can be embedded in an app. The component is dropped into your app, then polls a server for "manifests" available for that application and, if any are available, downloads the files described there. Unfortunately, the Updater Component is truly a sample application. Setup of the host is done manually, managing the host manifests and file repository is entirely manual, and there is virtually no client-side support for user prompting, custom progress UI's, etc. It is left to the developer to build out more robust features beyond simple update download. Update support is also limited exclusively to downloading files and assemblies. Still, the approach of using a lightweight client component that connects over HTTP via web services to perform simple update downloads was in line with the kind of solution I was looking for.
Ultimately, given the mismatch between commercial products and the features we required and the lack of robustness in free solutions, we chose to develop our own solution.
A Web-based Patch and Update Solution
Based on our requirements and the nature of our end-users, we determined that that our solution would have the following characteristics:
-
A client-side component agent that would be both very simple to implement, but also provide access to more detailed API's allowing the developer to have more control over the process with an investment greater implementation effort. It would support the ability to easily embed the agent component in update-enabled apps and we would also create a stand-alone agent - essentially an application using the component that runs in the SysTray. A config file would contain the identity of the update-enable application as well as settings controlling the agent behavior. These settings would also be exposed by the API, enabling the developer to control the agent behavior programmatically, if desired.
-
The update framework would support the ability to deliver new or updated files (which could include assembly .dlls), the ability to create and update client registry entries, the ability to invoke a custom .Net Installer assembly, and the ability to download and invoke an executable. Furthermore, the framework would be extensible, allowing us to add new custom update actions in the future, if need be.
-
We would create a web-based host application for managing the patches or updates available for a given application. Patches or updates would be published as "Manifests" describing the update contents, which would consist of "Manifest Items" of one of the aforementioned types. The client agent would communicate with this host via web services. The agent would poll the host for any Manifests appropriate to the application and current version it is associated with, then download the manifest contents, if desired - also via a web service. The administration application would be role-based, allowing the System Administrator to control the privileges of users defining Manifests in the system.
-
The client would provide default UI elements, such as progress indicators and prompts before downloading or applying updates. It would be possible to disable individual and/or all prompts, enabling "silent mode". The client would also support ability to override UI elements with customized versions, providing custom look-and-feel.
We also decided early on to design in some feature that would allow us to 'productize' our solution for sale to other developer's who want to build similar auto-update capabilities into their apps without investing all the time and effort we did. These features included support for managing updates for multiple companies, tools for simplifying certain processes, installers for the client SDK and server web applications, extra effort in terms of the usability of the web-based hosting application, as well as two levels of administrative roles in that app. A full list of the features in the final product, EverUpate, can be foundhere.
Design Details
Host Application
We built the Host application using ASP.Net with a SQL Server database. The database schema consists of primarily of Company, Application, Manifest, ManifestItem, and User tables. A Category table provides a folder-based organizational structure for Manifest Items. An intersection table representing a many-to-many relationship between ManifestItem and Categories provides the ability to define a Manifest Item once, but have it appear in multiple places in the Manifest Item organizational folders. Another intersection table between ManifestItem and Manifest allows one item to be associated with multiple manifests. This is useful when some component is used in multiple different applications, for instance.
| Fig 1 - General Table Schema |
|
|
|
Application |
| Id |
| CompanyId |
| Name | |
|
Application |
| Id |
| CompanyId |
| Name | |
|
Category |
| Id |
| Name |
| ParentId |
| CompanyId | |
| CategoryManifestItems |
| Id |
| CategorryId |
| ManifestItemId | |
|
|
|
Manifest |
| Id |
| CompanyId |
| AppId |
| Version |
| FinalVersion |
| Name |
| RebootRequired |
| BackupFiles | |
|
ManifestItem |
| Id |
| CompanyId |
| Name |
| Action |
| Type |
| Sequence |
| Version |
| RegistryTarget |
| FileSize |
| FileName |
| TargetPath |
| Args | |
|
|
User |
| Id |
| CompanyId |
| UserId |
| Role |
| FirstName |
| LastName | |
|
ManifestItemManifest |
| Id |
| ManifestId |
| ManifestItemId | |
Rather than developing a lot of custom code for querying these tables and for persisting data to them, we leveraged an opensource ORM (Object Relational Mapping) package calledOJB.NET. ORM's, like OJB.NET provide object-based access to relational databases, saving you from having to write a bunch of custom persistence code. While OJB.NET seems to be very much a grass-roots effort and is not as mature as similar packages that exist in the Java world (Hibernate, for example), it met our purposes well. I recommend you consider a package like this any time you're considering developing a database persistence layer.
The manifest management console was constructed almost entirely in ASP.NET with C# under the covers. As I mentioned earlier, since we anticipated marketing our final product to other developers, we put a fair amount
More articles from this pro: http://www.ArticlePros.com/author.php?Andrew Coulson
More on Computers & Internet
and
Programming can be found here.
|