开发者

Best practice for writing a self-updating windows service [closed]

Closed. This question is opinion-based. It is not currently accepting answers.

Want to improve this question? Update the question so it can be answered with开发者_如何学C facts and citations by editing this post.

Closed 2 years ago.

Improve this question

We need to create a windows service that has the ability to self update.

Three options spring to mind,

  1. a second service that manages the retrieval, uninstallation and installation of the first service.

  2. Use of some third party framework (suggestions welcome. I believe .NET supports automatic updating for windows forms apps, but not windows services)

  3. Use of a plugin model, whereby the service is merely a shell containing the updating and running logic, and the business logic of the service is contained in a DLL that can be swapped out.

Can anyone shed some light on the solution to this problem?

Thanks


Google have an open-source framework called Omaha which does exactly what your point 1. describes. It runs as a scheduled Windows task in the background, outside the applications it manages. Google use Omaha to auto-update their Windows applications, including Chrome. Because it comes from Google, and because it is installed on every Windows machine that runs Chrome, Omaha is extremely powerful.

There is an article online that explains in more detail how Omaha can be used to update Windows Services. It argues that Omaha is an especially good fit for Services (vs., say, GUI applications) because of its asynchronous nature.

So you could do your points 2. and 1. by using Omaha. I'm afraid I don't know how you would do 3.


Just some thoughts I had.

1 seems problematic because you end up dealing with the situation you're trying to resolve because at some point the updater will need updating. 3 sounds good but if by "swapped out" you mean using some fancy reflection to load the dll during run time I'm not sure if performance will become an issue.

There is a fourth option where the service can spawn an update process which would allow it to update the update executable if necessary before running it. From there it's a simple matter of writing an installation app which the service will spawn just before shutting down.


I use option 1. The updater process gets updated very rarely these days. It uses an XML file containing the details of where to get the files from (currently supports SVN, working on adding NuGet support) and where to put them. It also specifies which ones are services and which ones are websites and specifies the name of the service to use for each project.

The process polls the source, if there is a new version available it copies it down to a fresh version numbered directory and then updates the service. It also keeps 5 copies of each update making it easy to roll-back if there is a problem.

Here's the core piece of code for the updater which stops the existing service, copies the files over, and then restarts it.

if (isService)
{
    log.Debug("Stopping service " + project.ServiceName);

    var service = GetService(project);
    if (service != null && 
        service.Status != System.ServiceProcess.ServiceControllerStatus.Stopped && service.Status != System.ServiceProcess.ServiceControllerStatus.StopPending)
    {
        service.Stop();
    }

    service.WaitForStatus(System.ServiceProcess.ServiceControllerStatus.Stopped, new TimeSpan(0, 1, 0));
    if (service.Status == System.ServiceProcess.ServiceControllerStatus.Stopped)
        log.Debug("Service stopped");
    else
        log.Error("ERROR: Expected Stopped by Service is " + service.Status);

}

log.Debug("Copying files over");
CopyFolder(checkoutDirectory, destinationDirectory);

if (isService)
{
    log.Debug("Starting service");
    var service = GetService(project);

    // Currently it doesn't create services, you need to do that manually
    if (service != null)
    {
        service.Start();

        service.WaitForStatus(System.ServiceProcess.ServiceControllerStatus.Running, new TimeSpan(0, 1, 0));

        if (service.Status == System.ServiceProcess.ServiceControllerStatus.Running)
            log.Debug("Service running");
        else
            log.Error("Service " + service.Status);
    }
}
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜