Want to win a PS4? Go Premium and enter to win our High-Tech Treats giveaway. Enter to Win

x
?
Solved

Stop a NT Service while it is working

Posted on 2003-12-02
10
Medium Priority
?
500 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
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 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
VIDEO: THE CONCERTO CLOUD FOR HEALTHCARE

Modern healthcare requires a modern cloud. View this brief video to understand how the Concerto Cloud for Healthcare can help your organization.

 

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
 
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 1500 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

Concerto Cloud for Software Providers & ISVs

Can Concerto Cloud Services help you focus on evolving your application offerings, while delivering the best cloud experience to your customers? From DevOps to revenue models and customer support, the answer is yes!

Learn how Concerto can help you.

Question has a verified solution.

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

Introduction I have seen many questions in this Delphi topic area where queries in threads are needed or suggested. I know bumped into a similar need. This article will address some of the concepts when dealing with a multithreaded delphi database…
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 will teach you the special effect of super speed similar to the fictional character Wally West aka "The Flash" After Shake : http://www.videocopilot.net/presets/after_shake/ All lightning effects with instructions : http://www.mediaf…
This lesson discusses how to use a Mainform + Subforms in Microsoft Access to find and enter data for payments on orders. The sample data comes from a custom shop that builds and sells movable storage structures that are delivered to your property. …
Suggested Courses

636 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