Service-Anwendungen

Aus RAD Studio
Wechseln zu: Navigation, Suche

Nach oben zu Anwendungen erstellen

Service-Anwendungen nehmen Anforderungen von Client-Anwendungen entgegen, verarbeiten sie und geben Information an die Client-Anwendungen zurück. Normalerweise werden sie im Hintergrund ausgeführt, ohne dass der Benutzer viele Eingaben vorzunehmen braucht. Beispiele für Service-Anwendungen sind Web-, FTP- oder E-Mail-Server.

Um eine Anwendung zu erstellen, die einen Win32-Service implementiert, gehen Sie folgendermaßen vor:

  1. Wählen Sie Datei > Neu > Weitere und doppelklicken Sie im Dialogfeld Objektgalerie auf den Eintrag Service-Anwendung. Dadurch wird Ihrem Projekt die globale Variable Application hinzugefügt, die den Typ TServiceApplication hat.
  2. Es erscheint ein Fenster, das einem Service (TService) entspricht. Implementieren Sie den Service, indem Sie im Objektinspektor seine Eigenschaften und Ereignisbehandlungen einrichten.
  3. Sie fügen Ihrer Service-Anwendung zusätzliche Services hinzu, indem Sie Datei > Neu > Weitere wählen und im Dialogfeld Objektgalerie auf den Eintrag Service doppelklicken. Fügen Sie keine Services zu einer Anwendung hinzu, bei der es sich nicht um eine Service-Anwendung handelt. Während zwar ein TService-Objekt hinzugefügt werden kann, erzeugt die Anwendung nicht die erforderlichen Ereignisse, die veranlassen, dass die entsprechenden Windows-Aufrufe für den Service ausgeführt werden.
  4. Nachdem Sie die Service-Anwendung erstellt haben, installieren Sie Ihre Services mithilfe des Dienstkontroll-Managers. Andere Anwendungen starten Ihre Services, indem sie Anforderungen an den Dienstkontroll-Manager senden.

Um die Services Ihrer Anwendung zu installieren, führen Sie sie unter Verwendung der Option /INSTALL aus. Die Anwendung installiert ihre Services und beendet sich selbst. Falls die Services erfolgreich installiert werden konnten, erscheint eine Bestätigungsmeldung. Sie unterdrücken diese Meldung, indem Sie die Service-Anwendung unter Verwendung der Option /SILENT ausführen.

Um die Services zu deinstallieren, führen Sie sie mithilfe der Option /UNINSTALL von der Befehlszeile aus. (Um die Bestätigungsmeldung nach der Deinstallation zu unterdrücken, verwenden Sie zusätzlich die Option /SILENT.)

Anmerkung:  Dieser Service verfügt über ein TServerSocket, dessen Port auf 80 gesetzt ist. Das ist der Standard-Port für Web-Browser, um Anforderungen an Web-Server zu senden, und für Web-Server, um Antworten an Web-Browser zu senden. Das hier gezeigte Beispiel erzeugt ein Textdokument im Verzeichnis C:\Temp, WebLogxxx.log (wobei xxx die Thread-ID darstellt). Jeder Port sollte von jeweils nur einem Server genutzt werden. Wenn Sie also einen Web-Server haben, sollten Sie sicherstellen, dass er diesen Port nicht abfragt (der Service wird unterbrochen).

Um die Ergebnisse anzuzeigen, gehen Sie wie folgt vor: Öffnen Sie einen Web-Browser auf der lokalen Maschine und geben Sie als Adresse localhost ein. Der Browser wird irgendwann einen Timeout erzeugen, aber die Datei weblogxxx.log befindet sich im Verzeichnis C:\temp.

So erstellen Sie das Beispiel:

  1. Wählen Sie Datei > Neu > Weitere und im Dialogfeld Objektgalerie den Eintrag Service-Anwendung. Ein Fenster mit dem Namen Service1 wird angezeigt.
  2. Fügen Sie aus der Kategorie Internet der Tool-Palette eine ServerSocket-Komponente in das Service-Fenster (Service1) ein.
  3. Anschließend fügen Sie der Klasse TService1 ein private-Datenelement des Typs TMemoryStream hinzu. Der interface-Abschnitt Ihrer Unit sollte jetzt wie folgt aussehen:
 
 interface
 uses
   Windows, Messages, SysUtils, Classes, Graphics, Controls, SvcMgr, Dialogs,
   ScktComp;
 type
     TService1 = class(TService)
     ServerSocket1: TServerSocket;
     procedure ServerSocket1ClientRead(Sender: TObject;
       Socket: TCustomWinSocket);
     procedure Service1Execute(Sender: TService);
   private
     { private-Deklarationen }
     Stream: TMemoryStream; // fügen Sie diese Zeile hier ein
   public
     function GetServiceController: PServiceController; override;
     { public-Deklarationen }
   end;
 var
   Service1: TService1;
 //---------------------------------------------------------------------------
 #ifndef Unit1H
 #define Unit1H
 //---------------------------------------------------------------------------
 #include <SysUtils.hpp>
 #include <Classes.hpp>
 #include <SvcMgr.hpp>
 #include <ScktComp.hpp>
 //---------------------------------------------------------------------------
 class TService1 : public TService
 {
 __published:
 TServerSocket *ServerSocket1;
 private:
 TMemoryStream *Stream; // fügen Sie diese Zeile hier ein
 public:
 __fastcall TService1(TComponent* Owner);
 PServiceController __fastcall GetServiceController(void);
 friend void __stdcall ServiceController(unsigned CtrlCode);
 };
 //---------------------------------------------------------------------------
 extern PACKAGE TService1 *Service1;
 //---------------------------------------------------------------------------
 #endif
  1. Wählen Sie jetzt die in Schritt 1 hinzugefügte Komponente ServerSocket1 aus. Im Objektinspektor doppelklicken Sie auf das Ereignis OnClientRead und fügen die folgende Ereignisbehandlungsroutine ein:
 
 procedure TService1.ServerSocket1ClientRead(Sender: TObject;
   Socket: TCustomWinSocket);
 var
   Buffer: PChar;
 begin
   Buffer := nil;
 while Socket.ReceiveLength > 0 do begin
     Buffer := AllocMem(Socket.ReceiveLength);
     try
       Socket.ReceiveBuf(Buffer^, Socket.ReceiveLength);
       Stream.Write(Buffer^, StrLen(Buffer));
     finally
 				  FreeMem(Buffer);
     end;
   Stream.Seek(0, soFromBeginning);
   Stream.SaveToFile('c:\Temp\Weblog' + IntToStr(ServiceThread.ThreadID) + '.log');
   end;
 end;
 void __fastcall TService1::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, len);
 }
 __finally
 {
 free(Buffer);
 }
 Stream->Seek(0, soFromBeginning);
 AnsiString LogFile = "C:\\Temp\\WebLog";
 LogFile = LogFile + IntToStr(ServiceThread->ThreadID) + ".log";
 Stream->SaveToFile(LogFile);
 }
 }
  1. Schließlich wählen Sie Service1 aus, indem Sie in den Client-Bereich des Fensters klicken (aber nicht auf die ServerSocket-Komponente). Doppelklicken Sie im Objektinspektor auf das Ereignis OnExecute und fügen Sie die folgende Ereignisbehandlungsroutine ein:
 
 procedure TService1.Service1Execute(Sender: TService);
 begin
   Stream := TMemoryStream.Create;
   try
     ServerSocket1.Port := 80; // WWW-Port
     ServerSocket1.Active := True;
     while not Terminated do begin
       ServiceThread.ProcessRequests(True);
     end;
     ServerSocket1.Active := False;
   finally
     Stream.Free;
   end;
 end;
 void __fastcall TService1::Service1Execute(TService *Sender)
 {
 Stream = new TMemoryStream();
 try
 {
 ServerSocket1->Port = 80; // WWW-Port
 ServerSocket1->Active = true;
 while (!Terminated)
 ServiceThread->ProcessRequests(true);
 ServerSocket1->Active = false;
 }
 __finally
 {
 delete Stream;
 }
 }

Anmerkung:  Dienst-Anwendungen stehen bei plattformübergreifende Anwendungen nicht zur Verfügung.

Themen

Siehe auch