Best practice for writing a self-updating windows

2019-03-14 16:59发布

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

2条回答
闹够了就滚
2楼-- · 2019-03-14 17:44

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);
    }
}
查看更多
兄弟一词,经得起流年.
3楼-- · 2019-03-14 17:51

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.

查看更多
登录 后发表回答