Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is it possible to install multiple instances of the same delphi service application?

I have a service application built in Delphi that works great. It does exactly what I want it to do and all is happy. All is fine until I want to run two (or more) instances of that service on a single machine. Since the service name is hard coded into the program (via the Name property of the service), I can only install the service once on any given computer. If I try to modify the Name property at run-time, the service does not respond unless the Name property is set to the same thing that was set during design time.

I have done a workaround for this where I have all of the code that is not interacting directly with the service control manager encapsulated out into separate unit(s). Then I write a separate Delphi project for each instance that I want of the service that has just enough code to launch itself and start running the main code.

This method is, in my opinion, ugly and is certainly inefficient. It works okay for two instances, but then we need a third and a fourth and ...

Is there any way that I can modify my code so that I have just one Delphi project that can install and run itself as multiple service instances with some simple run-time input (e.g. command line flag)?

Or perhaps a broader question: Is there a "right way" to accomplish goal?

like image 305
Scott W Avatar asked Mar 04 '09 21:03

Scott W


4 Answers

You haven't made it clear what you have tried to change in the TService subclass.

Have you added a "BeforeInstall" handler?

Something like:

procedure TServiceMain.ServiceLoadInfo(Sender : TObject);// new method, not an override
begin
  Name := ParamStr(2);
  DisplayName := ParamStr(3);
end;

procedure TServiceMain.ServiceBeforeInstall(Sender: TService);
begin
  ServiceLoadInfo(Self);
end;
procedure TServiceMain.ServiceCreate(Sender: TObject);
begin
  ServiceLoadInfo(Self);
end;

If you do this regularly, subclass TService to do thie in the Constructor instead.

You should do the same in the BeforeUninstall as well - point both events at the same method.

C:\>servicename /install MyService "My Service Description"
like image 196
Gerry Coll Avatar answered Nov 08 '22 04:11

Gerry Coll


You can create your service with multiple threads internally, each one acting like it's own version/copy of the service. You control it with the Service Controller API, IIRC.

like image 29
Ken White Avatar answered Nov 08 '22 03:11

Ken White


Well yes it is possible to install multiple instances of the same service, you simply need to dynamically alter the name at install time (not runtime) however this does not make it desireable. (there is some sample code on Code project http://www.codeproject.com/KB/dotnet/MultipleInstNetWinService.aspx)

I would however be inclined to rethink your approach, service processes themselves are really meant to be singleton, if you need multiple instances of a process being run, maybe your service should just control and manage the multiple processes rather than being the process.

like image 2
Tim Jarvis Avatar answered Nov 08 '22 03:11

Tim Jarvis


The accepted answer above was awfully helpful.

Code I used:

procedure TService1.ServiceAfterInstall(Sender: TService);
begin
//http://stackoverflow.com/questions/612587/is-it-possible-to-install-multiple-instances-of-the-same-delphi-service-applicati
//http://www.c-sharpcorner.com/UploadFile/timosten/DynamicServiceInCSharp11262005062503AM/DynamicServiceInCSharp.aspx?ArticleID=4d5020e4-7317-425c-ab29-5bf37a1db421
//http://support.microsoft.com/kb/137890
  SaveRegSetting('\SYSTEM\CurrentControlSet\Services\' + Name, 'ImagePath', ParamStr(0) + ' --name=' + Name, HKEY_LOCAL_MACHINE)
end;

procedure TService1.ServiceCreate(Sender: TObject);
begin
  Name := Trim(FCommandLineOptions.Values['name']);
  DisplayName := Name;
end;

SaveRegSetting is my own procedure and FCommandLineOptions is an object that tokenises the command line parameters.

like image 1
cja Avatar answered Nov 08 '22 05:11

cja