Jump to content
thomh

Delphi service in a domain controlled environment

Recommended Posts

Hi, we have a bunch of customers running our Delphi coded RealThinClient server as a service in a domain controlled server environment.

 

They have set Windows Update to check for updates but not to automatically install them.

 

When the server does a Windows update check it happens often that our Delphi services stop responding.  If we stop the services we cannot start them again until we restart the server. Something happens in a domain controlled server environment when this Windows update check is done that messes up the services.

 

Our .Net services are not affected and keeps on running.

 

Has anybody seen or heard of this problem and is there a solution?

 

Thanks,

Thom

 

Share this post


Link to post

Hi David,

 

Delphi service that does nothing stops also. It might have something to do with how I start the service. This is straight from the RTC demo app. Is there a more "modern" way of starting the service?

 

function ServiceStart(const aMachine, aService: String) : Boolean;
var
  schm,
  schs: SC_Handle;
  ss: TServiceStatus;
  psTemp: PChar;
  dwChkP: DWord;
begin
  ss.dwCurrentState := 1;
  schm := OpenSCManager(PChar(aMachine), nil, SC_MANAGER_CONNECT);
  if (schm > 0) then
  begin
    schs := OpenService(schm, PChar(aService), SERVICE_START or SERVICE_QUERY_STATUS);
    if (schs > 0) then
    begin
      psTemp := nil;
      if (StartService(schs, 0, psTemp)) then
      begin
        if (QueryServiceStatus(schs, ss)) then
        begin
          while (SERVICE_RUNNING <> ss.dwCurrentState) do
          begin
            dwChkP := ss.dwCheckPoint;
            Sleep(ss.dwWaitHint);
            if (not QueryServiceStatus(schs, ss)) then
              Break;
            if (ss.dwCheckPoint < dwChkP) then
              Break;
          end;
        end;
      end;
      CloseServiceHandle(schs);
    end;
    CloseServiceHandle(schm);
  end;
  Result := SERVICE_RUNNING = ss.dwCurrentState;
end;
 

 

Share this post


Link to post

I think a standard Delphi service would be using TService.

http://docwiki.embarcadero.com/RADStudio/Sydney/en/Service_Applications

 

Just create a service project and put this in OnExecute event:

 procedure TService1.Service1Execute(Sender: TService);
 begin
   while not Terminated do 
     ServiceThread.ProcessRequests(True);
 end;

 

Edited by Cristian Peța

Share this post


Link to post

Our services runs on domain controlled servers and are descendents from TService, but they must be configured to run with a specific AD user (i.e. not the default system user) that has the necessary rights to access it's own file, and to start and stop services to be able to upgrade themselves. 

Share this post


Link to post
Guest

I would be rather surprised if this has anything to do with RTC itself.

However, building service code (or DI stuff) on demos can bite back.

I do know that some of the RTC demos are compatible back to... well very long.

So maybe you found a demo that was written with very long backwards compatibility in mind..

RTC do not make any presumptions on how you write your service DM.

I'd suggest you delve deep into TService and all that.

Also - this is a painful methodology, eps if the fault cannot be simulated in you dev environ - start to rip things out and see it it starts working.

 

HTH

Share this post


Link to post
On 2/23/2021 at 1:06 PM, Lars Fosdal said:

Our services runs on domain controlled servers and are descendents from TService, but they must be configured to run with a specific AD user (i.e. not the default system user) that has the necessary rights to access it's own file, and to start and stop services to be able to upgrade themselves. 

It's not related to the topic, but may I ask how you implemented the update mechanism? Without a "loader" (e.g. actual code is in a DLL, service only loads and executes the DLL,) I never managed to achieve this. I never figured out how to restart the service from within the service.

Share this post


Link to post
1 hour ago, aehimself said:

It's not related to the topic, but may I ask how you implemented the update mechanism? Without a "loader" (e.g. actual code is in a DLL, service only loads and executes the DLL,) I never managed to achieve this. I never figured out how to restart the service from within the service.

I usually use a seperate .exe located next to the service dll. The exutable stops the serive, does the updates, and restars the service.

The executable is ofcourse called by the service.

 

Another options is to create a seperate maintance service.

 

 

 

 

Edited by mvanrijnen

Share this post


Link to post
1 hour ago, aehimself said:

I never figured out how to restart the service from within the service.

It's not the best method but I run a batch file with

net stop ServiceName
net start ServiceName

 

Share this post


Link to post
3 hours ago, aehimself said:

I never figured out how to restart the service from within the service.

I never tried this, but there are some options for service recovery. If you exit the service with an error code, windows should restart it for you right away:

 

image.png.ea4fb7ec67280c5d0c343bbbb9f06498.png

 

Share this post


Link to post

Thank you all for the replies guys but I don't want to hijack OP's topic. The methods here seem to be "hacky" (to crash the service and let Windows to restart it - it's a tricky approach I have to admit, though!) or already tried (creating a batch file to sleep for 5 seconds, and issue the NET TOP/START commands. Issue is, as parent program stops, it stops the child processes and therefore the batch file execution too).

 

I was curious if there is a trick to restart a service from within the service itself without the need of a loader, maintenance service - an other executable in general. As it is not that important for me at the moment I'll just keep my eyes open to see if such method was unearthed already.

Share this post


Link to post
11 minutes ago, aehimself said:

creating a batch file to sleep for 5 seconds, and issue the NET STOP/START commands. Issue is, as parent program stops, it stops the child processes and therefore the batch file execution too

Why to sleep 5 second? And ShellExecute() doesn't create a child processes.

Share this post


Link to post
On 3/5/2021 at 10:41 PM, aehimself said:

Issue is, as parent program stops, it stops the child processes and therefore the batch file execution too

Why do you think so?

Share this post


Link to post
3 hours ago, Fr0sT.Brutal said:

Why do you think so?

 

1 hour ago, Lars Fosdal said:

Pretty simple but effective. Hasn't failed me yet. 

I tried creating a batch file from within the service. It slept 5 seconds (so I can see the process start) called NET STOP, slept 5 seconds (giving time for the service to stop) and NET START. When I called this batch from within the service I remember seeing the process starting and ending when the service terminated. This is why I never used this method.

As it works for others I am sure I did something wrong; unfortunately I don't have the code snipplet to debug now.

 

@Lars Fosdal this looks promising, I'll make a dummy service app to test it 🙂

Share this post


Link to post

@aehimself You need to have the unit as high as possible in the .dpr uses list to ensure that finalization is run as late as possible.

Share this post


Link to post
Guest

WOW! @Lars Fosdal, i used that quite succesfully in an application after you mentioned it last time (some ½ year?).

I had no ide it is possible to do that in a service.

 

If i can get this to work, then i could skip almost all 5 different VPN implementations on my own machines 🙂

Share this post


Link to post

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×