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

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

Ответ 1

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

Ответ 2

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()

Ответ 3

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

Ответ 4

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

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

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

Ответ 5

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

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

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

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

Ответ 6

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

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

Ответ 7

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

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

Ответ 8

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

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

Ответ 9

Проблема с обтеканием командного файла или 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) { }
}

Ответ 10

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

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

Ответ 11

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

Ответ 12

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

Ответ 13

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

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

Ответ 14

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

вы также можете генерировать исключение, это автоматически закроет службу Windows, а параметры автоматического повторного запуска просто начнут работать. Единственная проблема заключается в том, что если у вас есть среда разработки на вашем ПК, JIT пытается нажмите, и вы получите подсказку, в которой говорится об отладке Y/N. скажите "нет", а затем он закроется, а затем снова начнется правильно. (на ПК без JIT это все работает). причина в том, что JIT является новым для Win 7 (он отлично работал с XP и т.д.), и я пытаюсь найти способ отключения JIT.... я могу попробовать метод Environment.Exit, упомянутый здесь, посмотреть, как это тоже работает.

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

Ответ 15

Создайте файл restart.bat, подобный этому

@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%

Ответ 16

nssm довольно велик. он сделает все это за вас

Ответ 17

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

net stop net start

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

Ответ 18

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