Как служба windows может программно перезапустить себя?


Мне нужно написать надежный код в .NET, чтобы позволить службе windows (server 2003) перезапустить себя. Каков наилучший способ сделать это? Есть ли какой-то .NET API для этого?

18 123

18 ответов:

установите службу для перезапуска после сбоя (дважды щелкните службу в панели управления и посмотрите вокруг на этих вкладках - я забыл ее имя). Затем, в любое время, когда вы хотите перезапустить службу, просто позвоните Environment.Exit(1) (или любой ненулевой возврат), и ОС перезапустит его для вас.

Dim proc As New Process()
Dim psi As New ProcessStartInfo()

psi.CreateNoWindow = True
psi.FileName = "cmd.exe"
psi.Arguments = "/C net stop YOURSERVICENAMEHERE && net start YOURSERVICENAMEHERE"
psi.LoadUserProfile = False
psi.UseShellExecute = False
psi.WindowStyle = ProcessWindowStyle.Hidden
proc.StartInfo = psi
proc.Start()

вы не можете быть уверены, что учетная запись пользователя, под которой работает ваша служба, даже имеет разрешения на остановку и перезапуск службы.

const string strCmdText = "/C net stop \"SERVICENAME\"&net start \"SERVICENAME\"";
Process.Start("CMD.exe", strCmdText);

здесь SERVICENAME - это имя вашего сервиса (двойные кавычки, включенные для учета пробелов в имени сервиса, могут быть опущены в противном случае).

очистить, не требуется автоматическая перезагрузка конфигурации.

вы можете создать процесс, который является командной строкой DOS, которая перезапускает себя:

 Process process = new Process();
 process.StartInfo.FileName = "cmd";
 process.StartInfo.Arguments = "/c net stop \"servicename\" & net start \"servicename\"";
 process.Start();

Это будет зависеть от того, почему вы хотите, чтобы он перезапустился.

Если вы просто ищете способ периодически очищать службу, то у вас может быть таймер, работающий в службе, который периодически вызывает процедуру очистки.

Если вы ищете способ перезапуска при сбое-сам хост службы может предоставить эту возможность, когда он настроен.

Так зачем вам нужно перезапустить сервер? Чего вы пытаетесь достичь?

Я не думаю, что вы можете в Автономной службе (когда вы вызываете Restart, он остановит службу, которая прервет команду перезапуска, и она никогда не будет запущена снова). Если вы можете добавить второй .exe (консольное приложение, которое использует класс ServiceManager), то вы можете начать автономный .exe и пусть он перезапустит службу, а затем выйдет.

с другой стороны, вы, вероятно, могли бы зарегистрировать запланированную задачу службы (используя команду командной строки " at, например), чтобы запустить службу, а затем остановить ее; это, вероятно, сработает.

Я бы использовал планировщик Windows, чтобы запланировать перезапуск вашей службы. Проблема в том, что вы не можете перезапустить себя, но вы можете остановить себя. (Вы, по сути, отпилили ветку, на которой сидите... если вы понимаете мою аналогию) вам нужен отдельный процесс, чтобы сделать это за вас. Планировщик Windows является подходящим. Запланируйте однократную задачу перезапуска службы (даже из самой службы) для немедленного выполнения.

в противном случае, вам придется создайте "пастушеский" процесс, который делает это за вас.

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

самый чистый способ сделать это, который я нашел, - использовать метод OnStop (), который является точкой входа для диспетчера управления службами. Тогда весь ваш код очистки будет запущен, и у вас не будет никаких висячих сокетов или других процессов, предполагая, что ваш стоп-код выполняет свою работу.

для этого вам нужно установить флаг прежде чем вы завершите, это говорит методу OnStop выйти с кодом ошибки; тогда SCM знает, что служба должна быть перезапущена. Без этого флага вы не сможете остановить службу вручную из СКМ. Это также предполагает, что вы настроили службу для перезапуска при ошибке.

вот мой код:

...

bool ABORT;

protected override void OnStop()
{
    Logger.log("Stopping service");
    WorkThreadRun = false;
    WorkThread.Join();
    Logger.stop();
    // if there was a problem, set an exit error code
    // so the service manager will restart this
    if(ABORT)Environment.Exit(1);
}

Если служба сталкивается с проблемой и нуждается в перезапуске, я запускаю поток, который останавливает службу из SCM. Это позволяет службе очищать после себя:

...

if(NeedToRestart)
{
    ABORT = true;
    new Thread(RestartThread).Start();
}

void RestartThread()
{
    ServiceController sc = new ServiceController(ServiceName);
    try
    {
        sc.Stop();
    }
    catch (Exception) { }
}

Я не думаю, что это может. Когда служба "остановлена", она полностью разгружается.

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

первый ответ на вопрос является самым простым решением: "окружающая среда.Выход(1) " я использую это на Windows Server 2008 R2, и он отлично работает. Служба останавливается сама, O / S ждет 1 минуту, а затем перезапускает его.

создать отдельный домен для размещения кода приложения. Когда требуется перезагрузка, мы могли бы выгрузить и перезагрузить appdomain вместо процесса (служба windows). Вот как работает пул приложений IIS, они не запускаются asp.net приложение напрямую, они используют отдельный appdmain.

лучшим подходом может быть использование службы NT в качестве оболочки для вашего приложения. Когда служба NT запущена, ваше приложение может запускаться в режиме "простоя", ожидая запуска команды (или быть настроено на автоматический запуск).

подумайте о машине, когда она запускается, она начинает работать в режиме ожидания, ожидая, пока ваша команда пойдет вперед или назад. Это также позволяет использовать другие преимущества, такие как лучшее удаленное администрирование, поскольку вы можете выбрать, как выставить свой приложение.

просто проходя: и подумал, что я хотел бы добавить дополнительную информацию...

вы также можете бросить исключение, это автоматически закроет службу windows, и параметры автоматического повторного запуска просто удар. единственная проблема с этим заключается в том, что если у вас есть dev enviroment на вашем ПК, то JIT пытается пнуть, и вы получите приглашение сказать debug Y/N. скажите нет, а затем он закроется, а затем снова запустится правильно. (на ПК без JIT это просто все работает). причина im троллинг, это JIT является новым для Win 7 (он отлично работал с XP и т. д.), И я пытаюсь найти способ отключить JIT.... я могу попробовать окружающую среду.Метод выхода, упомянутый здесь, см., Как это работает.

Кристиан : Бристоль, Великобритания

создать перезагрузки.летучая мышь файл, как это

@echo on
set once="C:\Program Files\MyService\once.bat"
set taskname=Restart_MyService
set service=MyService
echo rem %time% >%once%
echo net stop %service% >>%once%
echo net start %service% >>%once%
echo del %once% >>%once%

schtasks /create /ru "System" /tn %taskname% /tr '%once%' /sc onstart /F /V1 /Z
schtasks /run /tn %taskname%

затем удалите задачу %taskname% при запуске %service%

nssm довольно большой. он сделает все это для вас

самый простой способ - иметь пакетный файл с:

чистая остановка чистый старт

и добавить этот файл в планировщик с желаемым интервалом времени

private static void  RestartService(string serviceName)
    {
        using (var controller = new ServiceController(serviceName))
        {
            controller.Stop();
            int counter = 0;
            while (controller.Status != ServiceControllerStatus.Stopped)
            {
                Thread.Sleep(100);
                controller.Refresh();
                counter++;
                if (counter > 1000)
                {
                    throw new System.TimeoutException(string.Format("Could not stop service: {0}", Constants.Series6Service.WindowsServiceName));
                }
            }

            controller.Start();
        }
    }