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