Best practice: Self-updating service?

Best practice: Self-updating service?

Have any of you written self-updating software? I am looking for a robust way for a service to restart itself after it has downloaded a new .exe version.  

14 thoughts on “Best practice: Self-updating service?

  1. There is 2 ways.

    1. you write very simple “luncher” that only downloads what is needed and lunches application and terminates itself. Usually luncher doesn’t need to be updated, but if needed you can do it with your main exe.

    2. I have used TMS component for updates. 

  2. The app can do the download by itself, so it is the restart bit that concerns me.  Not sure that I can use a launched app when running as a service, but might need a second service – depending on the user context that the service runs under?

  3. The service can launch some other application and end itself and the other app can then do all kinds of stuff.

    We are doing that in our application to update several services (they are running as SYSTEM).

  4. First off my mistakes; i only implemented one fetch of the new version and only one. In order to have beta-testers i should have an array of releases that could be downloaded (i.e. stable professional/betal proffesional, stable/personal…). Also i did not include any library files (DLLs so i need a reinstall out there for those updates. There is a balance between flexibility and security. Since my service only downloads a specific file from a specific place to a specific place there’s not much to “hack”. If i had instructions for what to download and copy on the server, then i would need more hardening.

    When my app installs (InnoSetup) it also installs a service – this is of course done in elevated mode. This service regularly polls an fixed hardcoded internet-server to check for a textfile with the version number. If it differs an exe is downloded to a subdirectory in the program dir along with a text file with new version number and download status.

    I upload the tested new binary before uploading the textfile so that the wrong version never gets downloaded. Also even though dates may be used, i have had the situation where more than one update had to be done the same day, so littering the place with dates is not optimal.

    When a new version is completely downloaded the status bar says there’s a new version, please close the application. Or if these is a new version and it has not yet been copied (by the service of course) a messagebox with a choice to terminate and update.

    => At application termination – if a new version is available – the service is sent a control message to copy the new version and another binary (Restart.exe) is run through the shell.

    => Restart.exe simply waits for the copy to finish, using a timer to check both files. When everything matches it terminates and restarts the application. Restart,exe is installed along with everything else. Restart.exe and the service are not possible to update automatically.

    Also, when other things get updated (database metadata i have a “least ok version” in the metadata so i can stop users from executing a version that can not handle the updated metadata but that is beside the point.

    I remember this was a lot of work debugging and getting to run smoothly but i also seem to recall that i did not use virtual machines at the time.



  5. Dany – We pull the version from a local db, which in turn pulls periodically from a central db.  There are several parameters and security measures that governs the validity of the version, so it is the restart that worried me.  I guess I can pass the PID of the current version to the relauncher, so that it can wait for the original service to terminate before launching the new one.  I hope to keep the relauncher as generic and stupid as possible.

  6. I haven’t written an updater for a service, only a normal app. When I did so:

     – the updater (download and installation) was a separate app. It launched normally to check for updates and to download the update; it launched itself with higher permissions to install the downloaded update (which required a UAC prompt.)

     – You can’t overwrite an EXE or DLL that’s running. You can rename them, though. So you can apply the update by renaming files in use, replacing them, and then on the restart of the machine or program, cleaning up the old versions.

     – The update should be able to update itself, too.

    Since you’re running a server the separate app thing may be trickier, but it’s a lot easier. Since you want a service to restart itself, it’s probably better to start the update service, and let that service stop and start the original one.

  7. What I typically do is to have the launcher start up (one or more) child processes and just wait for the child process id to terminate.  When it does terminate, first it looks to see if a new version is available and applies it if so, then it simply relaunches the child process.  Within the child process I usually have something periodically looking for new versions which shuts down the process if found.  That way the child process is in charge of shutting itself down in an orderly fashion.  For simplicity, there’s a NewVersion subfolder and both look for the same executable name within that subfolder (and must able to open the file exclusively to prevent a copy-in-progress from throwing the flag too quick.)  I’ve used this for 10+ years and rarely have a problem.  Build a little smarts into the launcher to detect version update problems (warn if it doesn’t have write access to the folder where the child process is executed)  You could have another deployment process that copies the new executable into the NewVersion folder whenever an update is available…when that happens the Child fairly soon shuts itself down, the launcher then immediately moves the NewVersion exec into place and then relaunches the updated child executable.  the only problem with this approach is if the child process is listening on a port as you may have a short period of time where you are not accepting new connections.  There’s other approaches for that.

  8. I did what Ilia Chachkhunashvili explains on 1), but if you don’t want a second app, you could do it with a single one and a batch file created on the fly as you can’t modify a running exe. The tricky part is updating a running app, here’s where the batch file comes to help, at this point you app must be terminated, then rename the new over the old, restart you app and finally you delete the batch file.

  9. Heinz Toskano – For a service, it’s not straightforward to use a batch file.  We have some server tasks that take several minutes to complete, so that means the service may not exit instantly, which makes it difficult to decide when to restart the service.

  10. Lars Fosdal does your server stop for maintenance reasons? you could then do the updates, as your services could detect when the server goes shutdown and restart. I think the best approach is to catch idle times, you can download the updates anytime, but apply on specific events. I think I have (somewhere) some code to allow exe replacement, need to find it.

  11. Heinz Toskano – The server is designed to run continuously and doesn’t really have idle times. All maintenance is done in-server or in parallel. Version delivery has been solved, so it is all about the restart. I wonder if I can pull it off by having a conditional launch in a finalization section?

Leave a Reply