Stop a NT Service while it is working

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
roburobeAsked:
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

ADSaundersCommented:
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
roburobeAuthor Commented:
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
ADSaundersCommented:
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
Introducing Cloud Class® training courses

Tech changes fast. You can learn faster. That’s why we’re bringing professional training courses to Experts Exchange. With a subscription, you can access all the Cloud Class® courses to expand your education, prep for certifications, and get top-notch instructions.

roburobeAuthor Commented:
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
ADSaundersCommented:
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
snehanshuCommented:
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
snehanshuCommented:
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

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
Lee_NoverCommented:
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
Lee_NoverCommented:
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
roburobeAuthor Commented:
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
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
Delphi

From novice to tech pro — start learning today.

Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.