Watch, Follow, &
Connect with Us

For forums, blogs and more please visit our
Developer Tools Community.


Welcome, Guest
Guest Settings
Help

Thread: Installing / running multiple instances of a TService



Permlink Replies: 3 - Last Post: Oct 19, 2016 12:19 PM Last Post By: Remy Lebeau (Te...
Mike Collins

Posts: 46
Registered: 9/23/05
Installing / running multiple instances of a TService
Click to report abuse...   Click to reply to this thread Reply
  Posted: Oct 19, 2016 4:33 AM
Hi all,

I know that this question has been raised MANY times so apologies for asking it again - I have followed the advise in previous posts and I cant seem to get it to work. I also know that what I'm asking / proposing is not necessarily the best approach, architecturally, but I'm looking for a bit of a quick fix.

So, I have a Win32 DataSnap service running on a server, providing connectivity for a mobile application. The service is providing a middle-tier between the App and a MS SQL Server database. All configurations for the service are store in an INI file that is local to the services installation directory.

Now, for one reason or another (essentially to provide separation demonstrations of our system) I want to run multiple copies / occurrences of this service from a single server. Whilst each new occurrence is located in a separation directory, obviously the Windows SCM does not allow registration of multiple services with the same ServiceName and DisplayName.

To address this problem, I have provided the facility where an ID can be passed, as a parameter, to each service. This ID is unique and relevant to the demonstration scenario i.e.

CMD> MyService /INSTALL /ID "12345"

Within my service I have created two functions to assign the ServiceName and DisplayName. Both these functions look for the command-line switch, ID, and if present, append the ID to the end of the default service name (or display name):

void TMyService::getServiceName(void)
{
	UnicodeString wzServiceName, wzId;
 
	wzServiceName = "MyServiceName";
 
	if ( FindCmdLineSwitch( "ID", wzId ) )
	{
		Name = UnicodeString( wzServiceName + "_" + wzId );
	}
	else
		Name = wzServiceName;
}


A similar function is provided to assign the Service DisplayName. The result of this is that the ServiceName will be set to "MyService_12345" and the DisplayName will be set to "My Service Name (12345)".

Within the Service I have coded BeforeInstall() and BeforeUninstall() events to call both of these functions (thereby assigning the correct ServiceName / DisplayName based on the parameter switch). In addition, I have an AfterInstall event that modifies the Bin path, for the Service, that is recorded with the SCM, to include the /ID parameter value (I did this using the ChangeServiceConfig() API instead of modifying the registry key directly as some posts suggested). Finally, in the constructor for the Service, if not installing, I also call my two name assignment functions:

__fastcall TMyService::TMyService(TComponent* Owner)
	: TService(Owner)
{
	if ( !Vcl::Svcmgr::Application->Installing() )
	{
		getServiceName();
		getServiceDisplayName();
		...
{


So, based on previous posts (shown below) I believe I have the same structure as others who report this working. I can install the base service (without the /ID switch) and it works fine i.e. installs and runs without issue. I can also install additional occurrence (using the /ID switch) and whilst they install fine (and appear correct in the SCM / registry), the service will not start. When I add debug trace, I find that the service is handing when I call my getServiceName(), at the point at which the new name is assign to the TService->Name.

Can anyone point me in the right direction here? Is it possible, in XE10, to do what I want?

Any help or advice would be gratefully received.

Mike C

https://gist.githubusercontent.com/JordiCorbilla/64eb194bcdc7e404dfee15db804c47ea/raw/4ff0cc41be68478bb632ddb9048b840e32fd2811/uServiceController.pas
http://www.codeproject.com/Articles/21320/Multiple-Instance-NET-Windows-Service
http://stackoverflow.com/questions/612587/is-it-possible-to-install-multiple-instances-of-the-same-delphi-service-applicat

Mike Collins

Posts: 46
Registered: 9/23/05
Re: Installing / running multiple instances of a TService
Click to report abuse...   Click to reply to this thread Reply
  Posted: Oct 19, 2016 5:34 AM   in response to: Mike Collins in response to: Mike Collins
Apologies - premature posting...

I have tracked down the issue. When initially installing, I was enclosing the /ID value in speech marks:

CMD> MyService /INSTALL /ID "12345"

Which was unnecessary. When updating the Bin path, I was also doing this. For some reason, during installation I was receiving 12345 and during service start I was receiving "12345" - the key difference being the speech marks. As soon as I removed these, everything seems to work fine.

Mike Collins wrote:
Hi all,
Remy Lebeau (Te...


Posts: 9,447
Registered: 12/23/01
Re: Installing / running multiple instances of a TService
Click to report abuse...   Click to reply to this thread Reply
  Posted: Oct 19, 2016 12:19 PM   in response to: Mike Collins in response to: Mike Collins
Mike wrote:

I have tracked down the issue. When initially installing, I was
enclosing the /ID value in speech marks:
CMD>> MyService /INSTALL /ID "12345"
CMD>>
Which was unnecessary.

Also irrelevant, since FindCmdLineSwitch() uses ParamStr(), which removes
surrounding quotes after parsing the parameter value from the command-line.

For some reason, during installation I was receiving 12345 and
during service start I was receiving "12345" - the key difference
being the speech marks.

That should not be happening. But, it is certainly easy to account for,
by using AnsiDequotedStr() inside your functions.

--
Remy Lebeau (TeamB)
Remy Lebeau (Te...


Posts: 9,447
Registered: 12/23/01
Re: Installing / running multiple instances of a TService
Click to report abuse...   Click to reply to this thread Reply
  Posted: Oct 19, 2016 12:16 PM   in response to: Mike Collins in response to: Mike Collins
Mike wrote:

Within the Service I have coded BeforeInstall() and BeforeUninstall()
events to call both of these functions (thereby assigning the correct
ServiceName / DisplayName based on the parameter switch).

You need to call them in the constructor instead, so that the new Name applies
not only during installation/uninstallation, but also during service executation
as well. When the SCM starts a service and sends messages to it, the service
Name is passed as a parameter, which TServiceApplication then uses to dispatch
the messages to the correct TService object (an executable may have multiple
services in it), so the requested Name needs to match the TService.Name at
all times.

Finally, in the constructor for the Service, if not installing, I also call
my two name assignment functions:

Get rid of the function calls in the Before(Un)Install events and just call
them unconditionally in the constructor only.

When I add debug trace, I find that the service is handing when I
call my getServiceName(), at the point at which the new name is
assign to the TService->Name.

Do you mean to say hanging instead of *handing*? Assigning the TService.Name
property should not be hanging anything when being assigned. Unless internally
it is trying to lock something that is already locked, which is not the case
in older Delphi versions, but who knows what v10 is doing nowadays.

--
Remy Lebeau (TeamB)
Legend
Helpful Answer (5 pts)
Correct Answer (10 pts)

Server Response from: ETNAJIVE02