A standalone Delphi application that can also be installed as windows service A standalone Delphi application that can also be installed as windows service windows windows

A standalone Delphi application that can also be installed as windows service


Totally possible. The trick is to edit the .dpr to create main form when you want to run as an application and the service form when you want to run as a service. Like this:

if SvComFindCommand('config') then begin  //When run with the /config switch, display the configuration dialog.  Forms.Application.Initialize;  Forms.Application.CreateForm(TfrmConfig, frmConfig);  Forms.Application.Run;endelse begin  SvCom_NTService.Application.Initialize;  SvCom_NTService.Application.CreateForm(TscmServiceSvc, scmServiceSvc);  SvCom_NTService.Application.Run;end;

The code above uses SvCom to run the service but exactly the same effect could be achieved using the standard TService.

I wrote an article about that for The Delphi Magazine many years ago. You can read it here: Many Faces Of An Application.


It'll be hard to explain but I will try :)

I've done it in my project like that (Delphi 5):

program TestSvc;uses SvcMgr,      SvcMain, //the unit for TTestService inherited from TService     ...     ;var  IsDesktopMode : Boolean;function IsServiceRunning : Boolean;var  Svc: Integer;  SvcMgr: Integer;  ServSt : TServiceStatus;begin  Result := False;  SvcMgr := OpenSCManager(nil, nil, SC_MANAGER_CONNECT);  if SvcMgr = 0 then Exit;  try    Svc := OpenService(SvcMgr, 'TestService', SERVICE_QUERY_STATUS);    if Svc = 0 then Exit;    try      if not QueryServiceStatus(Svc, ServSt) then Exit;      Result := (ServSt.dwCurrentState = SERVICE_RUNNING) or (ServSt.dwCurrentState = SERVICE_START_PENDING);    finally      CloseServiceHandle(Svc);    end;  finally    CloseServiceHandle(SvcMgr);  end;end;begin  if (Win32Platform <> VER_PLATFORM_WIN32_NT) or FindCmdLineSwitch('S', ['-', '/'], True)  then    IsDesktopMode := True  else begin    IsDesktopMode := not FindCmdLineSwitch('INSTALL', ['-', '/'], True) and      not FindCmdLineSwitch('UNINSTALL', ['-', '/'], True) and      not IsServiceRunning;  end;  if IsDesktopMode then begin //desktop mode    Forms.Application.Initialize;    Forms.Application.Title := 'App. Title';    ShowTrayIcon(Forms.Application.Icon.Handle, NIM_ADD); // This function for create an icon to tray. You can create a popupmenu for the Icon.    while GetMessage(Msg, 0, 0, 0) do begin      TranslateMessage(Msg);      DispatchMessage(Msg);    end;    ShowTrayIcon(Forms.Application.Icon.Handle, NIM_DELETE); // for delete the tray Icon  end else begin // Service mode    SvcMgr.Application.Initialize;    SvcMgr.Application.CreateForm(TTestService, TestService);    SvcMgr.Application.Run;  end;end.


Another almost simpler option is available at http://cc.embarcadero.com/item/19703, you just need to include a unit and change your DPR to something like:

begin  if CiaStartService('SERVICE NAME') then begin    CiaService.CreateForm(TMain, Main);    CiaService.Run;    Exit;  end;  Application.Initialize;  Application.Title := 'SERVICE NAME';  Application.CreateForm(TMain, Main);  Application.Run;end.

While this example is now quite dated, the technique is simple enough that it still works, even with Delphi XE2. With this in place, your application will continue to operate as a non-service until you use the "/install" parameter (on an elevated command prompt). After which it will operate as a service until you use the "/uninstall" parameter (also on an elevated command prompt).