views:

474

answers:

1

I am about to develop a program which will be installed and run as a Windows Service on the back-end servers (with internet access) of several clients. I do not have physical access to the servers. What I am working on is a scheme for reliably rolling out updates to the program.

I have spend quite a lot of time looking for best practices for Windows Service auto-updates, but have found very little useful information. Most techniques, such as ClickOnce, seem to cater primarily for Windows Forms-based applications.

My current plan is:

  • When updates are available, have the running service download, install, and start an update service.
  • The update service will download the new version of the main service and install it side-by-side of the current, still active version.
  • The update service next stops the old version and then starts the new version of the service.
  • The new version disables the update service during startup.

Some important concerns for me are:

  • Being able to handle updates both to the main service and the update service
  • Being able to handle interruptions such as power failure or a connection failure at any point during the update process

What am wondering is if this a common way to solve this problem and/or if I am missing anything crucial. Is it too complicated, or perhaps far too simplistic? How would you have done it (or, even better, how have you done this successfully)?

Thanks!

+6  A: 

I was faced with the same problem last year and I wrestled with a lot of the same questions. A few bits of advice:

  • Since either service may be updated, both services will function as updaters of the other. Service A will update Service B and vice versa. For this reason, I suggest simply running both services at all times. Unless you are worried about really loading down your server with does-update-exist calls, the enable/disable service management isn't worth the overhead.

  • Like services can't be installed on a single machine. In other words, you can't install new and old versions of the service side-by-side if they have the same name. Unless you want to complicate your update process, I suggest you uninstall the old version and then install the new version. For example, Service A would download Service B Installer, uninstall Service B, install new version of Service B and then run. Service B would do the same for Service A.

  • Since each service is managing the other, they should not only check for available updates but they should verify each other's health. For example, Service A would check to see if Service B exists and if it is running. If the health check fails, a list of steps to resolve the issue and get the service running would be completed by Service A. Executing the health check and recovery operations will cover you now matter what issue arises with the update, initial install or general operations.

  • Do ample logging on both the client and the server. You'll want to track what actions were taken and when. For example, Service A might when it is checking for updates, when it is executing the health check and associated actions. On the service (assuming you are calling into a web service looking for updates) track the calls made by each Service. If your Services aren't getting updated at least you'll have a trail of breadcrumbs (or lack of breadcrumbs) pointing you to the problem.

There are literally bunches of potential gotchas with a solution of this sort: services not running at startup, UAC getting in the way, not being able to install and uninstall the services with the same user, ensuring user installing the service has ample permissions, connectivity loss, getting the .NET Framework installed on the client machine, handling reboot after install if necessary, etc.

Best of luck. It's a fun problem to solve, but it doesn't go without it's frustration -- especially since, as you said, there isn't a lot of documented information available.

Ben Griswold
Thanks for valuable input. How did you handle the potential situation where the update process is interrupted after the old version is uninstalled but before the new one has been installed? Did you keep track of how far in the process you were?
Lars A. Brekken
I don't do incremental installs. The service is either installed and running or it isn't. Therefore I don't keep track of how far along the process I am. I *simply* use the health checks to determine if something isn't right and reattempt the installation if necessary.
Ben Griswold