RAD Studio
ContentsIndex
PreviousUpNext
Service Applications

Service applications take requests from client applications, process those requests, and return information to the client applications. They typically run in the background, without much user input. A Web, FTP, or e-mail server is an example of a service application.

To create an application that implements a Win32 service:

  1. Choose FileNewOther, and double-click Service Application in the New Items dialog box. This adds a global variable named Application to your project, which is of type TServiceApplication.
  2. A Service window appears that corresponds to a service (TService). Implement the service by setting its properties and event handlers in the Object Inspector.
  3. You can add additional services to your service application by choosing FileNewOther, and double-click Service in the New Items dialog box. Do not add services to an application that is not a service application. While a TService object can be added, the application will not generate the requisite events or make the appropriate Windows calls on behalf of the service.
  4. Once your service application is built, you can install its services with the Service Control Manager (SCM). Other applications can then launch your services by sending requests to the SCM.
To install your application's services, run it using the /INSTALL option. The application installs its services and exits, giving a confirmation message if the services are successfully installed. You can suppress the confirmation message by running the service application using the /SILENT option. 

To uninstall the services, run it from the command line using the /UNINSTALL option. (You can also use the /SILENT option to suppress the confirmation message when uninstalling).

Note: This service has a TServerSocket whose port is set to 80. This is the default port for Web browsers to make requests to Web servers and for Web servers to make responses to Web browsers. This particular example produces a text document in the C:\Temp directory called WebLogxxx.log (where xxx is the ThreadID). There should be only one server listening on any given port, so if you have a Web server, you should make sure that it is not listening (the service is stopped).
To see the results: open up a Web browser on the local machine and for the address, type 'localhost' (with no quotes). The browser will time out eventually, but you should now have a file called Weblogxxx.log in the C:\Temp directory.

To create the example:

  1. Choose FileNewOther and select Service Application from the New Items dialog box. The Service1 window appears.
  2. From the Internet category of the Tool palette, add a ServerSocket component to the service window (Service1).
  3. Add a private data member of type TMemoryStream to the TService1 class. The interface section of your unit should now look like this:

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 declarations }
    Stream: TMemoryStream; // Add this line here
  public
    function GetServiceController: PServiceController; override;
    { Public declarations }
  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; // add this line here
public:
__fastcall TService1(TComponent* Owner);
PServiceController __fastcall GetServiceController(void);
friend void __stdcall ServiceController(unsigned CtrlCode);
};
//---------------------------------------------------------------------------
extern PACKAGE TService1 *Service1;
//---------------------------------------------------------------------------
#endif

  1. Select ServerSocket1, the component you added in step 1. In the Object Inspector, double-click the OnClientRead event and add the following event handler:

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. Finally, select Service1 by clicking in the window's client area (but not on the ServiceSocket). In the Object Inspector, double click the OnExecute event and add the following event handler:

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;
}
}

When writing your service application, you should be aware of:

Note: Service applications are not available for cross-platform applications.

Copyright(C) 2009 Embarcadero Technologies, Inc. All Rights Reserved.
What do you think about this topic? Send feedback!