15 мая 2023 года "Исходники.РУ" отмечают своё 23-летие!
Поздравляем всех причастных и неравнодушных с этим событием!
И огромное спасибо всем, кто был и остаётся с нами все эти годы!

Главная Форум Журнал Wiki DRKB Discuz!ML Помощь проекту


Как написать NT Сервис в C++ Builder 4

Для создания приложения, которое является Win32 сервисом выберите File | New, а затем выберите Service Application на странице New Items:

В проект автоматически будет добавлена глобальная переменная Application, которая будет иметь тип TServiceApplication. Как только Вы создадите сервисное приложение, то сразу увидите окошко, которое отвечает за сервис (TService). У Сервиса так же есть свойства и обработчики событий, которые можно настроить в Object Inspector. Как только объект TService будет добавлен, то приложение уже не сможет генерировать стандартные события и оконные сообщения.

Пример: Ниже приведён пример сервиса, который имеет TServerSocket, порт которого установлен в 80. Так же этот пример создаёт текстовый файл в директории C:\Temp с именем WebLogxxx.log (где xxx это ThreadID). Каждым портом в системе может владеть только одно приложение, поэтому если у Вас запущен веб сервер, то необходимо его временно выключить (остановить сервис).

Для просмотра результатов, запустите браузер и в строке адреса наберите 'localhost' (без кавычек). Браузер выдаст тайм-аут, однако теперь появится файл weblogxxx.log в директории C:\temp.

  1. В File | New в диалоге New Items выберите Service Application. Появится окно Service1. Из закладки Internet в палитре компонентов добавьте компонент ServerSocket в окно сервиса (Service1).
  2. Далее добавьте в класс TService1, переменную типа TMemoryStream. Заголовочный файл будет выглядеть следующим образом:
    //-----------------------------------------------------------
    #ifndef Unit1H
    #define Unit1H
    //-----------------------------------------------------------
    
    #include <SysUtils.hpp>
    #include <Classes.hpp>
    #include <SvcMgr.hpp>
    #include <ScktComp.hpp>
    //-----------------------------------------------------------
    
    class TService1 : public TService
    {
    __published: // IDE-managed Components
      TServerSocket *ServerSocket1;
    
    private: // User declarations
      TMemoryStream *Stream; // add this line here
    
    public:  // User declarations
      __fastcall TService1(TComponent* Owner);
      PServiceController __fastcall GetServiceController(void);
      friend void __stdcall ServiceController(unsigned CtrlCode);
    };
    //-----------------------------------------------------------
    
    extern PACKAGE TService1 *Service1;
    //-----------------------------------------------------------
    
    #endif
  3. Далее выберите компонент ServerSocket1, в Object Inspector, сделайте двойной клик по событию OnClientRead и добавьте следующий код в обработчик события:
    void __fastcallTService1::ServerSocket1ClientRead(TObject
          *Sender, TCustomWinSocket *Socket)
    {
      char *Buffer = NULL;
      int len = Socket->ReceiveLength();
      while (len > 0)
      {
        try
        {
          Buffer = (char *)malloc(len);
          Socket->ReceiveBuf((void *)Buffer, len);
          Stream->Write(Buffer, strlen(Buffer));
        }
        __finally
        {
          free(Buffer);
        }
        Stream->Seek(0, soFromBeginning);
        AnsiString LogFile = "C:\\Temp\\WebLog";
        LogFile = LogFile + IntToStr(ServiceThread->ThreadID)
                          + ".log";
        Stream->SaveToFile(LogFile);
      }
    }
  4. В заключение, выберите Service1 и добавьте следующий код в обработчик события OnExecute:
    void __fastcall TService1::Service1Execute(TService *Sender)
    {
      Stream = new TMemoryStream();
      try
      {
        ServerSocket1->Port = 80; // WWW port
        ServerSocket1->Active = true;
        while (!Terminated)
           ServiceThread->ProcessRequests(false);
        ServerSocket1->Active = false;
      }
      __finally
      {
        delete Stream;
      }
    }