Forum > Windows

Windows service, self stop on condition

(1/3) > >>

cris75:
Hi,
with the help of the wiki and this (quite old) discussion https://forum.lazarus.freepascal.org/index.php/topic,20274.0.html, I successfully wrote some windows services, and they work as expected;
as a base of developing I used the approach by Udo Schmal here, https://www.gocher.me/Daemon in which he sets the FreeOnTerminate property of the thread to true when he starts the service;
when the service is started, I usually check for the existence of a config file from which I retrieve a handful of settings to be used in the execution;
as of today, if the config file does not exist I just don't go on and terminate the thread, but a thing I thought it was easy to do, that I've been not able to (and would like), is to "stop" (automatically) the service if this condition is met; probably I'm missing something..
if I'm not getting confused, I saw more than one time an "example" of what I'm saying, of a windows service that once started (by pressing "start" or with "net start servicename") automatically stops (for some reason, obviously), how could I reproduce this behavior?
Do you think it's possible?

cris75:
..no reply of any kind until now to my post.. I'm wondering if my question is silly or poorly asked.. If so forgive me in advance.. :'(

Bart:
It's a program, so you can stop it like any other program.
If it's derived from TCustomApplication then Application.Terminate should do.
And, of course, you could always do Halt();

You must have the OS configered not to restart this service when it stops.

Bart

cris75:

--- Quote ---You must have the OS configered not to restart this service when it stops
--- End quote ---

I don't think the operating system will restart the service if this one is "stopped" as you would usually do via services manager or by shell command "net stop service"..
but I assume maybe I don't understand what you're trying to explain me..  ::)

to be clear, this is the execute method of the thread:


--- Code: Pascal  [+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i < x.length; i++) { x[i].style.maxHeight='none'; x[i].style.height = Math.min(x[i].clientHeight+15,306)+'px'; x[i].style.resize = "vertical";}};} ---procedure TDaemonThread.Execute;var i: integer;begin  Parent.EventLog1.Info('Begin of Main thread');   i:= 0;  Application.Log(etDebug, 'Thread.Execute');  try    repeat      Sleep(1000); //milliseconds      inc(i);      Application.Log(etDebug, 'Thread.Loop ' + Format('Tick :%d', [i]));      if i = 5 then Terminate;  // this is an example condition for which the thread will be terminated    until Terminated;  // the loop will be exited because of the thread terminated  finally    Application.Log(etDebug, 'Thread.LoopStopped');  end;  { at this point how could I stop the service? }end;
I suppose that to get the behavior I want, the daemon has to know about the termination of the thread and somehow "stop" itself;
I use "Parent" declared in line 24 (see attached code) for EventLog, I thought "Parent.Stop" could have done it (stop the service) but i was wrong..

GetMem:
You should pass GenericDaemon to DaemonThread via the constructor. Something like this(not tested):


--- Code: Pascal  [+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i < x.length; i++) { x[i].style.maxHeight='none'; x[i].style.height = Math.min(x[i].clientHeight+15,306)+'px'; x[i].style.resize = "vertical";}};} ---  TGenericDaemon = class; //forward declaration   TDaemonThread = class(TThread)    Parent: TGenericDaemon;    FGenericDaemon: TGenericDaemon;  //add this    procedure SetParent(AOwner: TGenericDaemon);  protected    procedure Execute; override; //execute should be in protected section  public    constructor Create(AGenericDaemon: TGenericDaemon);   //add this                                                               destructor Destroy; override;   end;
Then on constructor create, assign GenericDaemon to a local variable:

--- Code: Pascal  [+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i < x.length; i++) { x[i].style.maxHeight='none'; x[i].style.height = Math.min(x[i].clientHeight+15,306)+'px'; x[i].style.resize = "vertical";}};} ---constructor TDaemonThread.Create(AGenericDaemon: TGenericDaemon);begin  inherited Create(True);  FGenericDaemon := AGenericDaemon;end;    
On Daemon start:

--- Code: Pascal  [+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i < x.length; i++) { x[i].style.maxHeight='none'; x[i].style.height = Math.min(x[i].clientHeight+15,306)+'px'; x[i].style.resize = "vertical";}};} ---  //...   FThread:= TDaemonThread.Create(Self); //add this  FThread.SetParent(self);  FThread.FreeOnTerminate:= true;  FThread.Start;
Finally on thread execute:

--- Code: Pascal  [+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i < x.length; i++) { x[i].style.maxHeight='none'; x[i].style.height = Math.min(x[i].clientHeight+15,306)+'px'; x[i].style.resize = "vertical";}};} ---procedure TDaemonThread.Execute;var i: integer;begin  Parent.EventLog1.Info('Begin of Main thread');   i:= 0;  Application.Log(etDebug, 'Thread.Execute');  try    repeat      Sleep(1000); //milliseconds      inc(i);      Application.Log(etDebug, 'Thread.Loop ' + Format('Tick :%d', [i]));      if i = 5 then FGenericDaemon.Stop;//add this    until Terminated;  // the loop will be exited because of the thread terminated  finally    Application.Log(etDebug, 'Thread.LoopStopped');  end;  { at this point how could I stop the service? }end; 

Navigation

[0] Message Index

[#] Next page

Go to full version