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.

Comments

  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.

    ReplyDelete
  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?

    ReplyDelete
  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).

    ReplyDelete
  4. 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.

    ReplyDelete
  5. I misread all. You want to update a service. Sorry about that.
    Why not do everything from a dedicated update service? Stop - Copy - Start?

    ReplyDelete
  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.

    ReplyDelete
  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.

    ReplyDelete
  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.

    ReplyDelete
  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.

    ReplyDelete
  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.

    ReplyDelete
  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?

    ReplyDelete

Post a Comment