Solved

Stop a NT Service while it is working

Posted on 2003-12-02
10
477 Views
Last Modified: 2010-04-05
Hello everybody!!!

I made a NT Service with Delphi 5 Enterprise.
This Service, is always waiting for a file and sometimes makes some job that lasts 2 minutes.
If I try to stop the service when it is working, I can't do this. I must wait the end of the job and then, when the service is IDLE, I can press the "Stop" button.

I'd like to have the "stopping" dialog that stills until the job is done and then the service stops regularly.

What can I do?
If I'm not so clear, please, ask me more!!

Roberto
0
Comment
Question by:roburobe
  • 3
  • 3
  • 2
  • +1
10 Comments
 
LVL 10

Expert Comment

by:ADSaunders
ID: 9858438
Hi roburobe,
Don't know about Delphi, But in Any other language including VB, I'd declare a global Boolean (logical) variable (e.g. StopMe) Initially set at false. The 'stop' button Onclick event simply changes the value of this variable to True, and possibly changes displayed text. The server process loop checks the value of this variable at every iteration, and if set to true, gracefully exits.
Point to note: You will have to ensure that events are propagated so that the button click is seen. If the server process is intensive, (IN VB) i'd liberally sprinkle the code with DoEvents statements, there should be something comparable in Delphi.

Regards .. Alan
0
 

Author Comment

by:roburobe
ID: 9858621
Thanks Alan,

I put a global variable called "EndPending" that is checked at the end of each work. If set to true, the whole service stops.

But it still doesn't works!!! In the OnStop Event of the Service, I placed a loop that checks that the job has ended. At the end, I put Stopped to True. Now, the message that says that the service cannot be stopped, appears in less than a second, ignoring my loop!!! How can I tell the Service Control Panel to wait?

Thanks

Roberto
0
 
LVL 10

Expert Comment

by:ADSaunders
ID: 9858774
IN the OnStop event, first set the variable to true, then check for termination. (i.e. reverse what you've done)
That way, the service gets the trigger to stop after the next iteration, and the service manager sees the termination after the wait loop.
0
 

Author Comment

by:roburobe
ID: 9859200
Hello ADSaunders,

Here's my OnStop event:

procedure TAutopostel.ServiceStop(Sender: TService; var Stopped: Boolean);
begin
  EndPending := True; // Tell the working job that the user asked to end the service
  Stopped := True;
  While not Ended do // ended is set to true by the working job at the end of the work
                             // and only if endpending is True
  begin
    Sleep(500);
    ReportStatus; // I read it in the help....
  end;
end;

Something's wrong?
0
 
LVL 10

Expert Comment

by:ADSaunders
ID: 9859225
Sorry, I did say I didn't know Delphi. I have used a similar technique in VB before though.

Once again my apologies, maybe someone with some Delphi experience can help.

.. Alan
0
Is Your Active Directory as Secure as You Think?

More than 75% of all records are compromised because of the loss or theft of a privileged credential. Experts have been exploring Active Directory infrastructure to identify key threats and establish best practices for keeping data safe. Attend this month’s webinar to learn more.

 
LVL 5

Expert Comment

by:snehanshu
ID: 9859391
roburobe,
  I am not sure about this, but does this help (Call ReportStatus before Sleep)?

procedure TAutopostel.ServiceStop(Sender: TService; var Stopped: Boolean);
begin
  EndPending := True; // Tell the working job that the user asked to end the service
  Stopped := True;
  While not Ended do // ended is set to true by the working job at the end of the work
                             // and only if endpending is True
  begin
    ReportStatus; // I read it in the help....
    Sleep(500);
  end;
end;

...Shu
0
 
LVL 5

Accepted Solution

by:
snehanshu earned 500 total points
ID: 9863675
roburobe,
>> Now, the message that says that the service cannot be stopped, appears in less than a
>>second, ignoring my loop!!!
  Are you sure that Ended provides you the correct status. I mean, is Ended always "False" when there is some other process going on and does it become true after the processes complete?

To test, you could make your service "interactive", and add a showmessage in the stop code and also tweak it as follows:

procedure TAutopostel.ServiceStop(Sender: TService; var Stopped: Boolean);
begin
  EndPending := True; // Tell the working job that the user asked to end the service
  Stopped := False;//Set it to false initially

  ReportStatus; // Report status before the loop also

  If Ended then
    showmessage('Ended is True')
  Else
    showmessage('Ended is False');

  While not Ended do // ended is set to true by the working job at the end of the work
                             // and only if endpending is True
  begin
    ReportStatus; // I read it in the help....
    Sleep(500);
  end;
  Stopped := False;//Set it to True after the while loop
end;
0
 
LVL 12

Expert Comment

by:Lee_Nover
ID: 9864596
do not use unprotected global variables in services ! each service runs in it's own thread ! (you might have several instances of a service)
first create an event with manual control and defalt to signaled(TEvent class in SyncObjs - dunno if D5 has this .. if not then use CreateEvent API)
when your job starts reset the event and when the job ends set the event
in the OnStop event check for this event: MyEvent.WaitFor(INFINITE) or WaitForSingleObject(hEvent, ...)
the thread that called the Stop method will wait until the job has ended or the timeout period has elapsed
you'll still have to allow your service to get the stop message (DoEvents -vb, Application.ProcessMessages -delphi)
you do this with the following procedure

  {:Process all messages waiting in the current thread's message queue.
    @author  gabr
    @since   2003-08-25
  }        
  procedure DSiProcessThreadMessages;
  var
    msg: TMsg;
  begin
    while PeekMessage(Msg, 0, 0, 0, PM_REMOVE) and (Msg.Message <> WM_QUIT) do begin
      TranslateMessage(Msg);
      DispatchMessage(Msg);
    end;
  end; { DSiProcessThreadMessages }


you could however stop the job forcefuly also by setting somekind of an event and checking it during processing
0
 
LVL 12

Expert Comment

by:Lee_Nover
ID: 9864899
ugh ... forget that procedure :) my bad .. you simply call ServiceThread.ProcessRequests(false);
also be careful for deadlocks :)
btw .. that stopping dialog progress can't be stopped .. it periodically checks the service status
you could return the status immediately and notify show a message saying the service is finishing the job .. when done display it's done and stop the service
0
 

Author Comment

by:roburobe
ID: 9865823
snehanshu, you are quite right..... I put some file writing in the ServiceStop method and I see that if I press the "Stop" button in the SCM while the service is doing his job, nothing is written (and the "error" is reported)... at the end of the job, the file is written and the Service taken down.

Probably, the job is very intensive and the software has no time to start the "ServiceStop" event handler.
Now my problem is allow the service to start the ServiceStop Event even if it's working.... Do you have some suggestion?

Thanks

Roberto
0

Featured Post

Is Your Active Directory as Secure as You Think?

More than 75% of all records are compromised because of the loss or theft of a privileged credential. Experts have been exploring Active Directory infrastructure to identify key threats and establish best practices for keeping data safe. Attend this month’s webinar to learn more.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Suggested Solutions

Have you ever had your Delphi form/application just hanging while waiting for data to load? This is the article to read if you want to learn some things about adding threads for data loading in the background. First, I'll setup a general applica…
Introduction Raise your hands if you were as upset with FireMonkey as I was when I discovered that there was no TListview.  I use TListView in almost all of my applications I've written, and I was not going to compromise by resorting to TStringGrid…
This tutorial gives a high-level tour of the interface of Marketo (a marketing automation tool to help businesses track and engage prospective customers and drive them to purchase). You will see the main areas including Marketing Activities, Design …
Internet Business Fax to Email Made Easy - With eFax Corporate (http://www.enterprise.efax.com), you'll receive a dedicated online fax number, which is used the same way as a typical analog fax number. You'll receive secure faxes in your email, fr…

896 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

17 Experts available now in Live!

Get 1:1 Help Now