Мне нужно написать надежный код в .NET, чтобы служба Windows (сервер 2003) перезапустить себя. Каков наилучший способ так это? Есть ли .NET API для этого?
Мне нужно написать надежный код в .NET, чтобы служба Windows (сервер 2003) перезапустить себя. Каков наилучший способ так это? Есть ли .NET API для этого?
Ответы:
Настройте сервис на перезапуск после сбоя (дважды щелкните сервис на панели управления и посмотрите на эти вкладки - я забыл его название). Затем в любое время, когда вы захотите перезапустить сервис, просто позвоните Environment.Exit(1)
(или любой ненулевой возврат), и ОС перезапустит его для вас.
Service.ExitCode = 1
и затем выполнить, Service.Stop()
а также включить флажок «Включить действия для остановок с ошибками» на экране настроек восстановления службы. Делая это таким образом, вы сможете правильно завершить работу и запустить перезагрузку.
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()
Вы не можете быть уверены, что учетная запись пользователя, под которой работает ваша служба, даже имеет разрешения для остановки и перезапуска службы.
Вы можете создать процесс, который является командной строкой DOS, который перезапускает себя:
Process process = new Process();
process.StartInfo.FileName = "cmd";
process.StartInfo.Arguments = "/c net stop \"servicename\" & net start \"servicename\"";
process.Start();
const string strCmdText = "/C net stop \"SERVICENAME\"&net start \"SERVICENAME\"";
Process.Start("CMD.exe", strCmdText);
где SERVICENAME
- название вашего сервиса (двойные кавычки, включенные для учета пробелов в имени сервиса, в противном случае могут быть опущены).
Чисто, не требуется автоматическая перезагрузка конфигурации.
Это будет зависеть от того, почему вы хотите перезапустить себя.
Если вы просто ищете способ периодически очищать службу, то у вас может быть запущен таймер, который периодически вызывает процедуру очистки.
Если вы ищете способ перезапуска при сбое - сервисный хост сам может предоставить эту возможность при настройке.
Так зачем вам перезагружать сервер? Чего ты пытаешься достичь?
Я не думаю, что вы можете сделать это в автономной службе (когда вы вызываете Restart, она останавливает службу, что прерывает команду Restart и больше никогда не запускается). Если вы можете добавить второй .exe-файл (консольное приложение, использующее класс ServiceManager), то вы можете запустить автономный .exe-файл, запустить его, а затем выйти.
Подумав еще раз, вы, вероятно, могли бы заставить службу зарегистрировать запланированное задание (например, с помощью команды 'at' из командной строки), чтобы запустить службу и затем остановить ее самостоятельно; это, вероятно, сработает.
Проблема с выделением командного файла или EXE заключается в том, что служба может иметь или не иметь разрешения, необходимые для запуска внешнего приложения.
Самый чистый способ сделать это - использовать метод OnStop (), который является точкой входа для Service Control Manager. Тогда весь ваш код очистки будет запущен, и у вас не будет зависающих сокетов или других процессов, если ваш код остановки выполняет свою работу.
Для этого перед завершением вам нужно установить флаг, который сообщает методу 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) { }
}
Я бы использовал планировщик Windows, чтобы запланировать перезапуск вашего сервиса. Проблема в том, что вы не можете перезапустить себя, но вы можете остановить себя. (Вы, по сути, отпилили ветку, на которой сидите ... если вы поймете мою аналогию) Вам нужен отдельный процесс, чтобы сделать это для вас. Планировщик Windows является подходящим. Запланируйте одноразовое задание для немедленного запуска службы (даже из самой службы).
В противном случае вам придется создать «пастырский» процесс, который сделает это за вас.
Первый ответ на этот вопрос - самое простое решение: «Environment.Exit (1)». Я использую его в Windows Server 2008 R2, и он отлично работает. Служба останавливается, O / S ждет 1 минуту, затем перезапускает.
Лучшим подходом может быть использование службы NT в качестве оболочки для вашего приложения. Когда служба NT запущена, ваше приложение может запускаться в режиме ожидания, ожидая запуска команды (или быть настроено на автоматический запуск).
Подумайте об автомобиле: когда он запускается, он начинает работать в режиме ожидания, ожидая, пока ваша команда пойдет вперед или назад. Это также дает другие преимущества, такие как улучшенное удаленное администрирование, так как вы можете выбрать способ представления своего приложения.
Просто мимоходом и подумал, что я хотел бы добавить дополнительную информацию ...
Вы также можете выдать исключение, это автоматически закроет службу Windows, и параметры автоматического перезапуска просто включаются. Единственная проблема с этим заключается в том, что если у вас есть среда разработки на вашем компьютере, то JIT пытается включить, и вы получите подсказку отладки Y / N. скажи нет, и тогда он закроется, а затем перезапустится правильно. (на ПК без JIT все просто работает). причина, по которой я троллю, заключается в том, что этот JIT является новым для Win 7 (раньше он работал нормально с XP и т. д.), и я пытаюсь найти способ отключить JIT .... я могу попробовать упомянутый здесь метод Environment.Exit и посмотреть, как это тоже работает.
Кристиан: Бристоль, Великобритания
Создайте файл 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%
Создайте отдельный домен приложения для размещения кода приложения. Когда требуется перезагрузка, мы можем выгрузить и перезагрузить домен приложения вместо процесса (служба Windows). Вот как работает пул приложений IIS: они не запускают приложение asp.net напрямую, они используют отдельный appdmain.
Самый простой способ - создать командный файл с:
чистый стоп чистый старт
и добавьте файл в планировщик с желаемым интервалом времени
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();
}
}