Skip to content

Building the DataSnap Server

March 27, 2011

Design Goals

  • EXE will be able to run as a stand-alone application and as an NT Service.
  • Server will support multiple departments through the use of multiple Server Classes.
  • Server will use DBX and the Native SQL Client for database access.
  • Server UI will show how many clients are connected to the server.

 

Getting Started

First start Delphi XE and go File->New->Other and select the DataSnap Server category. Then Double Click the DataSnap Server icon and set the wizard options as follows.

image

image

Use the default port of 211 and click the finish button. Now you’ve got a DataSnap server that will run as an NT service. Be sure to save everything before continuing.

Now, lets add the form for the UI when the server runs in stand-alone mode. Right click on the the server exe in the project manager and select Add New->Form. You can change the name of the form if like. I called mine THPDMainFormUI.

Updating the server to run as a service and a stand-alone application

The server .dpr will need to be updated to allow the application to show the UI if we are in stand-alone mode. First we need to add two new methods, one to tell us if we are installing the service and one to tell us if we are installed as a service and need to start as a service.

Here is the source for the completed server .dpr

program HPDServer;

uses
  SvcMgr,
  Forms,
  SysUtils,
  WinSvc,
  Windows,
  BaseServerContainerUnit in 'BaseServerContainerUnit.pas' {HPDService: TService},
  HPDMainForm in 'HPDMainForm.pas' {HPDMainFormUI};

{$R *.RES}

function Installing: Boolean;
begin
  result := FindCmdLineSwitch('install', true) or
            FindCmdLineSwitch('uninstall', true);
end;

{ This function checks to see if the service has been registered. If it has
  the appserver will start as a service. If you want to run this server as
  a standalone process, unregister the service.}
function RunAsService: Boolean;
var
  Mgr, Svc: Integer;
  UserName, ServiceStartName: string;
  Config: Pointer;
  Size: DWord;
begin
  Result := False;
  Mgr := OpenSCManager(nil, nil, SC_MANAGER_ALL_ACCESS);
  if Mgr <> 0 then
  begin
    Svc := OpenService(Mgr, PChar(HPDService.Name), SERVICE_ALL_ACCESS);
    Result := Svc <> 0;
    if Result then
    begin
      QueryServiceConfig(Svc, nil, 0, Size);
      Config := AllocMem(Size);
      try
        QueryServiceConfig(Svc, Config, Size, Size);
        ServiceStartName := PQueryServiceConfig(Config)^.lpBinaryPathName;
      finally
        Dispose(Config);
      end;
      CloseServiceHandle(Svc);
    end;
    CloseServiceHandle(Mgr);
  end;

  if Result then
  begin
    Size := MAX_PATH;
    SetLength(UserName, Size);
    UserName := Forms.Application.ExeName;
    SetLength(UserName, StrLen(PChar(UserName)));
    Result := CompareText(UserName, ServiceStartName) = 0;
  end;
end;

begin
  // Windows 2003 Server requires StartServiceCtrlDispatcher to be
  // called before CoRegisterClassObject, which can be called indirectly
  // by Application.Initialize. TServiceApplication.DelayInitialize allows
  // Application.Initialize to be called from TService.Main (after
  // StartServiceCtrlDispatcher has been called).
  //
  // Delayed initialization of the Application object may affect
  // events which then occur prior to initialization, such as
  // TService.OnCreate. It is only recommended if the ServiceApplication
  // registers a class object with OLE and is intended for use with
  // Windows 2003 Server.
  //
  // Application.DelayInitialize := True;
  //
  if Installing or RunAsService then
  begin
    if (Win32Platform = VER_PLATFORM_WIN32_NT) and
      (((Win32MajorVersion = 5) and (Win32MinorVersion >= 2)) or
        (Win32MajorVersion > 5)) then
      SvcMgr.Application.DelayInitialize := True;

    if not SvcMgr.Application.DelayInitialize or SvcMgr.Application.Installing then
      SvcMgr.Application.Initialize;
    SvcMgr.Application.CreateForm(THPDService, HPDService);
  SvcMgr.Application.Run;
  end
  else
  begin
    Forms.Application.Initialize;
    Forms.Application.MainFormOnTaskBar := True;
    Forms.Application.CreateForm(THPDMainFormUI, HPDMainFormUI);
    Forms.Application.Run;
  end;
end.

You project manager should look something like this.
image
 Next time we will add a TDSServerClass to our server and start retrieving data from the database.
Advertisements
No comments yet

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: