Лучшие практики для написания самообновляющейся службы Windows - PullRequest
24 голосов
/ 22 октября 2009

Нам нужно создать службу Windows, которая имеет возможность самообновления.

На ум приходят три варианта,

  1. второй сервис, который управляет поиском, удалением и установкой первого сервиса.

  2. Использование некоторых сторонних фреймворков (предложения приветствуются. Я считаю, что .NET поддерживает автоматическое обновление для приложений форм Windows, но не служб Windows)

  3. Использование модели плагинов, при которой служба представляет собой просто оболочку, содержащую логику обновления и запуска, а бизнес-логика службы содержится в DLL, которую можно заменить.

Может кто-нибудь пролить свет на решение этой проблемы?

Спасибо

Ответы [ 2 ]

4 голосов
/ 22 октября 2009

Просто некоторые мысли, которые у меня были.

1 кажется проблематичным, потому что вы в конечном итоге сталкиваетесь с ситуацией, которую пытаетесь разрешить, потому что в какой-то момент средство обновления будет нуждаться в обновлении. 3 звучит неплохо, но если под словом «выгрузить» вы подразумеваете использование какого-то необычного отражения для загрузки библиотеки DLL во время выполнения, я не уверен, что производительность станет проблемой.

Существует четвертый вариант, когда служба может порождать процесс обновления, который позволит ей обновлять исполняемый файл обновления при необходимости перед его запуском. Оттуда просто написать приложение для установки, которое будет порождаться сервисом непосредственно перед выключением.

1 голос
/ 18 сентября 2011

Я использую вариант 1. В настоящее время процесс обновления обновляется очень редко. Он использует XML-файл, содержащий информацию о том, где получить файлы (в настоящее время поддерживает SVN, работает над добавлением поддержки NuGet) и где их разместить. В нем также указывается, какие из них являются службами, а какие - веб-сайтами, и указывается название службы, используемой для каждого проекта.

Процесс опрашивает источник, если доступна новая версия, он копирует ее в каталог с новой версией с номером и затем обновляет службу. Он также сохраняет 5 копий каждого обновления, что упрощает откат в случае возникновения проблемы.

Вот основной фрагмент кода для программы обновления, которая останавливает существующую службу, копирует файлы и затем перезапускает ее.

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);
    }
}
...