Как остановить сервис (TService)
От: Kelasant  
Дата: 22.04.05 09:48
Оценка:
Привет!
Написал сервис, с использованием Service Application. (Builder 6.0)
Работает хорошо. Осталась одна проблема.
Хочу, что бы он красиво останавливался.
Например, нажатием кнопки стоп в списке сервисов
или программно через SCM.
Как заставить этот сервис реагировать на команду Стоп?
Помогите, плиз.
Re: Как остановить сервис (TService)
От: Danchik Украина  
Дата: 22.04.05 11:13
Оценка:
Здравствуйте, Kelasant, Вы писали:

K>Привет!

K>Написал сервис, с использованием Service Application. (Builder 6.0)
K>Работает хорошо. Осталась одна проблема.
K>Хочу, что бы он красиво останавливался.
K>Например, нажатием кнопки стоп в списке сервисов
K>или программно через SCM.
K>Как заставить этот сервис реагировать на команду Стоп?
K>Помогите, плиз.

Первое что приходит в глову — так это то что ты неправильно реализовал сервис. Останавливатся он должен.
Скорее залип он где то, а где — это надо смотреть. Пришли что ли кусок кода...
Re[2]: Как остановить сервис (TService)
От: Kelasant  
Дата: 22.04.05 12:26
Оценка:
Здравствуйте, Danchik, Вы писали:

D>Здравствуйте, Kelasant, Вы писали:


K>>Привет!

K>>Написал сервис, с использованием Service Application. (Builder 6.0)
K>>Работает хорошо. Осталась одна проблема.
K>>Хочу, что бы он красиво останавливался.
K>>Например, нажатием кнопки стоп в списке сервисов
K>>или программно через SCM.
K>>Как заставить этот сервис реагировать на команду Стоп?
K>>Помогите, плиз.

D>Первое что приходит в глову — так это то что ты неправильно реализовал сервис. Останавливатся он должен.

D>Скорее залип он где то, а где — это надо смотреть. Пришли что ли кусок кода...

Присылаю.

//---------------------------------------------------------------------------
#include <stdio.h>
#include "Main.h"
#include "LogFile.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"

TKelaDatabaseService *KelaDatabaseService;


//---------------------------------------------------------------------------
__fastcall TKelaDatabaseService::TKelaDatabaseService(TComponent* Owner)
  : TService(Owner)
{
}
//---------------------------------------------------------------------------

TServiceController __fastcall TKelaDatabaseService::GetServiceController(void)
{
  return (TServiceController) ServiceController;
}
//---------------------------------------------------------------------------

void __stdcall ServiceController(unsigned CtrlCode)
{
  KelaDatabaseService->Controller(CtrlCode);
}
//---------------------------------------------------------------------------

// пустые обработчики с логированием
void __fastcall TKelaDatabaseService::ServiceBeforeInstall(TService *Sender)
{  WriteLog("c:\\_service.log",      "Service before install\n", MyLog);}
void __fastcall TKelaDatabaseService::ServiceAfterInstall(TService *Sender)
{  WriteLog("c:\\_service.log",      "Service after install\n", MyLog);}
void __fastcall TKelaDatabaseService::ServiceBeforeUninstall(TService *Sender)
{  WriteLog("c:\\_service.log",      "Service before uninstall\n", MyLog);}
void __fastcall TKelaDatabaseService::ServiceAfterUninstall(TService *Sender)
{  WriteLog("c:\\_service.log",      "Service after uninstall\n", MyLog);}
void __fastcall TKelaDatabaseService::ServiceDestroy(TObject *Sender)
{  WriteLog("c:\\_service.log",      "Service destroy\n", MyLog);}
void __fastcall TKelaDatabaseService::ServiceShutdown(TService *Sender)
{  WriteLog("c:\\_service.log",      "Service shutdown\n", MyLog);}
void __fastcall TKelaDatabaseService::ServicePause(TService *Sender, bool &Paused)
{  WriteLog("c:\\_service.log",      "Service pause\n", MyLog);}
void __fastcall TKelaDatabaseService::ServiceContinue(TService *Sender, bool &Continued)
{  WriteLog("c:\\_service.log",      "Service continue\n", MyLog);}
void __fastcall TKelaDatabaseService::ServiceStart(TService *Sender, bool &Started)
{  WriteLog("c:\\_service.log",      "Service start\n", MyLog);}
void __fastcall TKelaDatabaseService::ServiceCreate(TObject *Sender)
{  WriteLog("c:\\_service.log",      "Service create\n", MyLog);}
//---------------------------------------------------------------------------

void __fastcall TKelaDatabaseService::ServiceStop(TService *Sender, bool &Stopped)
{
  // сюда он почему-то не заходит... :(
  ServiceMustDestroyed = true;
  WriteLog("c:\\_service.log", "Service stop\n", MyLog);
}
//---------------------------------------------------------------------------

void __fastcall TKelaDatabaseService::ServiceExecute(TService *Sender)
{
  WriteLog("c:\\_service.log", "Service execute begin\n", MyLog);
  ::Sleep(1000);

  if (LoadDLL() != 0)
    return;

  ComTList = new TThreadList();

  // здесь я делаю некий сервер, который я вырезал.
  IdTCPServer1 = new TIdTCPServer(NULL);
  IdTCPServer1->DefaultPort  = 34567;
  IdTCPServer1->OnConnect    = SConnect;
  IdTCPServer1->OnExecute    = SExecute;
  IdTCPServer1->OnDisconnect = SDisconnect;
  IdTCPServer1->Active = true;
  // далее он работает независимо в отдельном потоке


  // условие окончания работы сервиса
  ServiceMustDestroyed = false;

  // главный цикл

  // вышеуказанный сервер может по команде клиента присвоить ServiceMustDestroyed = true
  // и корректно самостоятельно закончить выполнение
  while (ServiceMustDestroyed == false)
  {
    WriteLog("c:\\_service.log", ".\n", MyLog);
    ::Sleep(5000);

    // здесь выдает статус "Stopped", хотя при этом успешно работает - что есть непонятно....
    switch (Status)
    {
      csStopped         : { WriteLog("c:\\_service.log", "...csStopped\n", MyLog); break;}
      csStartPending    : { WriteLog("c:\\_service.log", "...csStartPending\n", MyLog); break;}
      csStopPending     : { WriteLog("c:\\_service.log", "...csStopPending\n", MyLog); break;}
      csRunning         : { WriteLog("c:\\_service.log", "...csRunning\n", MyLog); break;}
      csContinuePending : { WriteLog("c:\\_service.log", "...csContinuePending\n", MyLog); break;}
      csPausePending    : { WriteLog("c:\\_service.log", "...csPausePending\n", MyLog); break;}
      csPaused          : { WriteLog("c:\\_service.log", "...csPaused\n", MyLog); break;}
    }
  }

  // напоследок подождем немного
  ::Sleep(5000);

  WriteLog("c:\\_service.log", "Service execute end\n", MyLog);
}


Что тут может быть не то?
По команде, которую я отправляю через клиента сервера, реализованного внутри сервиса,
переменная ServiceMustDestroyed = true и сервис корректно останавливается.
Да и в целом все работает.

Вот только почему он не останавливается по команде стоп в списке служб?
Выдает сообщение через пару секунд типа:

---------------------------
Services
---------------------------
Could not stop the DCPP Database Service service on Local Computer.
The service did not return an error. This could be an internal Windows error or an internal service error.
If the problem persists, contact your system administrator.
---------------------------
OK
---------------------------

А в логе не видно ни единого вызова какого-либо обработчика.
Помогите!
Re[2]: Как остановить сервис (TService) (изменил ответ)
От: Kelasant  
Дата: 22.04.05 12:30
Оценка:
Здравствуйте, Danchik, Вы писали:

D>Здравствуйте, Kelasant, Вы писали:


K>>Привет!

K>>Написал сервис, с использованием Service Application. (Builder 6.0)
K>>Работает хорошо. Осталась одна проблема.
K>>Хочу, что бы он красиво останавливался.
K>>Например, нажатием кнопки стоп в списке сервисов
K>>или программно через SCM.
K>>Как заставить этот сервис реагировать на команду Стоп?
K>>Помогите, плиз.

D>Первое что приходит в глову — так это то что ты неправильно реализовал сервис. Останавливатся он должен.

D>Скорее залип он где то, а где — это надо смотреть. Пришли что ли кусок кода...

Присылаю.

//---------------------------------------------------------------------------
#include <stdio.h>
#include "Main.h"
#include "LogFile.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"

TKelaDatabaseService *KelaDatabaseService;


//---------------------------------------------------------------------------
__fastcall TKelaDatabaseService::TKelaDatabaseService(TComponent* Owner)
  : TService(Owner)
{
}
//---------------------------------------------------------------------------

TServiceController __fastcall TKelaDatabaseService::GetServiceController(void)
{
  return (TServiceController) ServiceController;
}
//---------------------------------------------------------------------------

void __stdcall ServiceController(unsigned CtrlCode)
{
  KelaDatabaseService->Controller(CtrlCode);
}
//---------------------------------------------------------------------------

// пустые обработчики с логированием
void __fastcall TKelaDatabaseService::ServiceBeforeInstall(TService *Sender)
{  WriteLog("c:\\_service.log",      "Service before install\n", MyLog);}
void __fastcall TKelaDatabaseService::ServiceAfterInstall(TService *Sender)
{  WriteLog("c:\\_service.log",      "Service after install\n", MyLog);}
void __fastcall TKelaDatabaseService::ServiceBeforeUninstall(TService *Sender)
{  WriteLog("c:\\_service.log",      "Service before uninstall\n", MyLog);}
void __fastcall TKelaDatabaseService::ServiceAfterUninstall(TService *Sender)
{  WriteLog("c:\\_service.log",      "Service after uninstall\n", MyLog);}
void __fastcall TKelaDatabaseService::ServiceDestroy(TObject *Sender)
{  WriteLog("c:\\_service.log",      "Service destroy\n", MyLog);}
void __fastcall TKelaDatabaseService::ServiceShutdown(TService *Sender)
{  WriteLog("c:\\_service.log",      "Service shutdown\n", MyLog);}
void __fastcall TKelaDatabaseService::ServicePause(TService *Sender, bool &Paused)
{  WriteLog("c:\\_service.log",      "Service pause\n", MyLog);}
void __fastcall TKelaDatabaseService::ServiceContinue(TService *Sender, bool &Continued)
{  WriteLog("c:\\_service.log",      "Service continue\n", MyLog);}
void __fastcall TKelaDatabaseService::ServiceStart(TService *Sender, bool &Started)
{  WriteLog("c:\\_service.log",      "Service start\n", MyLog);}
void __fastcall TKelaDatabaseService::ServiceCreate(TObject *Sender)
{  WriteLog("c:\\_service.log",      "Service create\n", MyLog);}
//---------------------------------------------------------------------------

void __fastcall TKelaDatabaseService::ServiceStop(TService *Sender, bool &Stopped)
{
  // сюда он почему-то не заходит... :(
  ServiceMustDestroyed = true;
  WriteLog("c:\\_service.log", "Service stop\n", MyLog);
}
//---------------------------------------------------------------------------

void __fastcall TKelaDatabaseService::ServiceExecute(TService *Sender)
{
  WriteLog("c:\\_service.log", "Service execute begin\n", MyLog);
  ::Sleep(1000);

  // здесь я делаю некий сервер, который я вырезал.
  IdTCPServer1 = new TIdTCPServer(NULL);
  IdTCPServer1->DefaultPort  = 34567;
  IdTCPServer1->OnConnect    = SConnect;
  IdTCPServer1->OnExecute    = SExecute;
  IdTCPServer1->OnDisconnect = SDisconnect;
  IdTCPServer1->Active = true;
  // далее он работает независимо в отдельном потоке


  // условие окончания работы сервиса
  ServiceMustDestroyed = false;

  // главный цикл

  // вышеуказанный сервер может по команде клиента присвоить ServiceMustDestroyed = true
  // и корректно самостоятельно закончить выполнение
  while (ServiceMustDestroyed == false)
  {
    WriteLog("c:\\_service.log", ".\n", MyLog);
    ::Sleep(5000);

    // здесь выдает статус "Stopped", хотя при этом успешно работает - что есть непонятно....
    switch (Status)
    {
      csStopped         : { WriteLog("c:\\_service.log", "...csStopped\n", MyLog); break;}
      csStartPending    : { WriteLog("c:\\_service.log", "...csStartPending\n", MyLog); break;}
      csStopPending     : { WriteLog("c:\\_service.log", "...csStopPending\n", MyLog); break;}
      csRunning         : { WriteLog("c:\\_service.log", "...csRunning\n", MyLog); break;}
      csContinuePending : { WriteLog("c:\\_service.log", "...csContinuePending\n", MyLog); break;}
      csPausePending    : { WriteLog("c:\\_service.log", "...csPausePending\n", MyLog); break;}
      csPaused          : { WriteLog("c:\\_service.log", "...csPaused\n", MyLog); break;}
    }
  }

  // напоследок подождем немного
  ::Sleep(5000);

  WriteLog("c:\\_service.log", "Service execute end\n", MyLog);
}


Что тут может быть не то?
По команде, которую я отправляю через клиента сервера, реализованного внутри сервиса,
переменная ServiceMustDestroyed = true и сервис корректно останавливается.
Да и в целом все работает.

Вот только почему он не останавливается по команде стоп в списке служб?
Выдает сообщение через пару секунд типа:

---------------------------
Services
---------------------------
Could not stop the DCPP Database Service service on Local Computer.
The service did not return an error. This could be an internal Windows error or an internal service error.
If the problem persists, contact your system administrator.
---------------------------
OK
---------------------------

А в логе не видно ни единого вызова какого-либо обработчика.
Помогите!
Re[3]: Как остановить сервис (TService)
От: Danchik Украина  
Дата: 22.04.05 12:43
Оценка:
Здравствуйте, Kelasant, Вы писали:

K>Полный Skip


Все, вижу твою траблу
Опять же те же грабли Ты не то событие использовал для запуска сервиса.
Это уже оговаривалось моной здесь

OnExecute — почитай help, используется когда тебе нужно выполнить что то. При выходе изи OnExcute — сервис автоматически останавливается. Не юзай это событие.

Че делать:
На OnStарт — стартуй поток который делает то что ты написал в Execute
На OnStop — останавливай поток
OnExecute вытри

Есть правда возможность работы и с OnExecute, но тогда ты должен вызывать ProcessRequests метод (RTFM). Не пробовал но наверняка реально

Удачи!
Re[4]: Как остановить сервис (TService)
От: Kelasant  
Дата: 22.04.05 13:56
Оценка:
Здравствуйте, Danchik, Вы писали:

D>Все, вижу твою траблу

D>Опять же те же грабли Ты не то событие использовал для запуска сервиса.
D>Это уже оговаривалось моной здесь

D>OnExecute — почитай help, используется когда тебе нужно выполнить что то. При выходе изи OnExcute — сервис автоматически останавливается. Не юзай это событие.


D>Че делать:

D>На OnStарт — стартуй поток который делает то что ты написал в Execute
D>На OnStop — останавливай поток
D>OnExecute вытри

D>Есть правда возможность работы и с OnExecute, но тогда ты должен вызывать ProcessRequests метод (RTFM). Не пробовал но наверняка реально


D>Удачи!


Спасибо, буду пробовать.......
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.