Как служба Windows может программно перезапустить себя? - PullRequest
128 голосов
/ 21 октября 2008

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

Ответы [ 18 ]

181 голосов
/ 21 октября 2008

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

22 голосов
/ 31 мая 2011
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()
15 голосов
/ 21 октября 2008

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

9 голосов
/ 12 апреля 2013
const string strCmdText = "/C net stop \"SERVICENAME\"&net start \"SERVICENAME\"";
Process.Start("CMD.exe", strCmdText);

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

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

9 голосов
/ 12 февраля 2009

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

 Process process = new Process();
 process.StartInfo.FileName = "cmd";
 process.StartInfo.Arguments = "/c net stop \"servicename\" & net start \"servicename\"";
 process.Start();
5 голосов
/ 21 октября 2008

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

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

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

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

3 голосов
/ 27 апреля 2016

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

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

Для этого вам необходимо установить флаг перед завершением, который сообщает методу OnStop для выхода с кодом ошибки; тогда SCM знает, что служба должна быть перезапущена. Без этого флага вы не сможете вручную остановить службу из 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) { }
}
3 голосов
/ 21 октября 2008

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

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

2 голосов
/ 03 марта 2009

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

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

1 голос
/ 13 июля 2015

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

...