Watch, Follow, &
Connect with Us

For forums, blogs and more please visit our
Developer Tools Community.


Welcome, Guest
Guest Settings
Help

Thread: Problems with Windows Service in XE7


This question is answered.


Permlink Replies: 6 - Last Post: Oct 15, 2015 5:51 AM Last Post By: Flavio Redi
Flavio Redi

Posts: 4
Registered: 11/3/14
Problems with Windows Service in XE7  
Click to report abuse...   Click to reply to this thread Reply
  Posted: Oct 9, 2015 12:04 PM
Hi,

I developed a Windows Service app in XE7. All worked fine, but when I tried to stop the service I got a windows error. I tried a lot of things to solve, but I couldn't. Finally, I created a new Windows Service Project with only a loop in the OnExecute event and I got the same error. I did the same in XE6 and all worked normally.

Does anybody know if XE7 has a bug in Windows Service develpment??
Remy Lebeau (Te...


Posts: 9,447
Registered: 12/23/01
Re: Problems with Windows Service in XE7
Helpful
Click to report abuse...   Click to reply to this thread Reply
  Posted: Oct 9, 2015 7:35 PM   in response to: Flavio Redi in response to: Flavio Redi
Flavio wrote:

I developed a Windows Service app in XE7. All worked fine, but
when I tried to stop the service I got a windows error. I tried a lot
of things to solve, but I couldn't. Finally, I created a new Windows
Service Project with only a loop in the OnExecute event and I got
the same error. I did the same in XE6 and all worked normally.

You are not managing the service correctly, preventig it from processing
SCM requests correctly. Please show your actual code that is not working.

I strongly suggest NOT using the OnExecute event at all. Most people implement
it wrong. It is better to start a worker thread in the OnStart event and
terminate it in the OnStop/OnShutdown events. Don't even assign an OnExecute
handler at all, then TService can focus on processing SCM requests without
interference.

Does anybody know if XE7 has a bug in Windows Service develpment??

Not that I am aware of. In fact, the TService framework has changed very
little over the years (which I have complained about many times).

--
Remy Lebeau (TeamB)
Flavio Redi

Posts: 4
Registered: 11/3/14
Re: Problems with Windows Service in XE7  
Click to report abuse...   Click to reply to this thread Reply
  Posted: Oct 14, 2015 5:56 AM   in response to: Remy Lebeau (Te... in response to: Remy Lebeau (Te...
Remy Lebeau (TeamB) wrote:
Flavio wrote:

I developed a Windows Service app in XE7. All worked fine, but
when I tried to stop the service I got a windows error. I tried a lot
of things to solve, but I couldn't. Finally, I created a new Windows
Service Project with only a loop in the OnExecute event and I got
the same error. I did the same in XE6 and all worked normally.

You are not managing the service correctly, preventig it from processing
SCM requests correctly. Please show your actual code that is not working.

I strongly suggest NOT using the OnExecute event at all. Most people implement
it wrong. It is better to start a worker thread in the OnStart event and
terminate it in the OnStop/OnShutdown events. Don't even assign an OnExecute
handler at all, then TService can focus on processing SCM requests without
interference.

Does anybody know if XE7 has a bug in Windows Service develpment??

Not that I am aware of. In fact, the TService framework has changed very
little over the years (which I have complained about many times).

--
Remy Lebeau (TeamB)

If it is not a bug in XE7, why it works normally with same code but compiled in XE6??
Remy Lebeau (Te...


Posts: 9,447
Registered: 12/23/01
Re: Problems with Windows Service in XE7  
Click to report abuse...   Click to reply to this thread Reply
  Posted: Oct 14, 2015 10:31 AM   in response to: Flavio Redi in response to: Flavio Redi
Flavio wrote:

If it is not a bug in XE7, why it works normally with same code
but compiled in XE6??

I can't answer that since you have not shown the actual code yet.

--
Remy Lebeau (TeamB)
Flavio Redi

Posts: 4
Registered: 11/3/14
Re: Problems with Windows Service in XE7  
Click to report abuse...   Click to reply to this thread Reply
  Posted: Oct 14, 2015 12:24 PM   in response to: Remy Lebeau (Te... in response to: Remy Lebeau (Te...
Remy Lebeau (TeamB) wrote:
Flavio wrote:

If it is not a bug in XE7, why it works normally with same code
but compiled in XE6??

I can't answer that since you have not shown the actual code yet.

--
Remy Lebeau (TeamB)

I tryied to switch to thread, but the error still remains.

Code:
type
  TsvcTeste = class(TService)
    procedure ServiceStop(Sender: TService; var Stopped: Boolean);
    procedure ServiceStart(Sender: TService; var Started: Boolean);
  private
    { Private declarations }
    FThread: TThread;
  public
    function GetServiceController: TServiceController; override;
    { Public declarations }
  end;
 
  TTestThread = class(TThread)
  private
    FService: TsvcTeste;
    { Private declarations }
  protected
    procedure Execute; override;
  public
    property Service: TsvcTeste read FService write FService;
  end;
 
var
  svcTeste: TsvcTeste;
 
implementation
 
procedure ServiceController(CtrlCode: DWord); stdcall;
begin
  svcTeste.Controller(CtrlCode);
end;
 
function TsvcTeste.GetServiceController: TServiceController;
begin
  Result := ServiceController;
end;
 
procedure TsvcTeste.ServiceStart(Sender: TService; var Started: Boolean);
begin
  Started := True;
  FThread := TTestThread.Create(True);
  TTestThread(FThread).Service := Self;
  FThread.Start;
end;
 
procedure TsvcTeste.ServiceStop(Sender: TService; var Stopped: Boolean);
begin
  FThread.Terminate;
  Stopped := False;
end;
 
procedure TTestThread.Execute;
begin
  { Place thread code here }
  while not Self.Terminated do
  begin
   Sleep(1000);
   //Service.ServiceThread.ProcessRequests(True);
  end;
end;
 
end.
Remy Lebeau (Te...


Posts: 9,447
Registered: 12/23/01
Re: Problems with Windows Service in XE7
Correct
Click to report abuse...   Click to reply to this thread Reply
  Posted: Oct 14, 2015 1:27 PM   in response to: Flavio Redi in response to: Flavio Redi
Flavio wrote:

I tryied to switch to thread, but the error still remains.

In your OnStop event handler, you are setting the Stopped parameter to False
instead of True. As such, the service is not actually stopping.

TService automatically sets its Status property to csStopPending before calling
OnStop, and automatically sets its Status to csStopped if OnStop returns
Stopped=True, but it does not automatically reset the Status back to csRunning
if OnStop returns with Stopped=False. Also, you need to report the current
Status periodically to the SCM while waiting for your worker thread to terminate.

So, in this case, the SCM ends up timing out waiting for a status change
and reports an error because it thinks your service failed to stop correctly
(which is true).

Try this instead:

interface
 
uses
  Classes, SvcMgr;
 
type
  TsvcTeste = class(TService)
    procedure ServiceStop(Sender: TService; var Stopped: Boolean);
    procedure ServiceStart(Sender: TService; var Started: Boolean);
    procedure ServiceShutdown(Sender: TService);
  private
    { Private declarations }
    FThread: TThread;
  public
    function GetServiceController: TServiceController; override;
    { Public declarations }
  end;
 
var
  svcTeste: TsvcTeste;
 
implementation
 
type
  TTestThread = class(TThread)
  private
    FService: TsvcTeste;
    { Private declarations }
  protected
    procedure Execute; override;
  public
    constructor Create(AService: TsvcTeste); reintroduce;
    property Service: TsvcTeste read FService;
  end;
 
procedure ServiceController(CtrlCode: DWord); stdcall;
begin
  svcTeste.Controller(CtrlCode);
end;
 
function TsvcTeste.GetServiceController: TServiceController;
begin
  Result := ServiceController;
end;
 
procedure TsvcTeste.ServiceStart(Sender: TService; var Started: Boolean);
begin
  FThread := TTestThread.Create(Self);
  Started := True;
end;
 
procedure TsvcTeste.ServiceStop(Sender: TService; var Stopped: Boolean);
begin
  ServiceShutdown(Sender);
  Stopped := True;
end;
 
procedure TsvcTeste.ServiceShutdown(Sender: TService);
begin
  if FThread <> nil then
  begin
    FThread.Terminate;
 
    // TThread.WaitFor() blocks until the thread is terminated, but the service's
    // current status (csStopPending) needs to be reported periodically so 
the SCM
    // does not time out...
 
    //FThread.WaitFor;
    while WaitForSingleObject(FThread.Handle, Self.WaitHint-10) = WAIT_TIMEOUT 
do
      Self.ReportStatus;
 
    FreeAndNil(FThread;
  end;
end;
 
constructor TTestThread.Create(AService: TsvcTeste);
begin
  inherited Create(False);
  FService := AService;
end;
 
procedure TTestThread.Execute;
begin
  while not Terminated do
  begin
    // do some work...
    Sleep(1000);
 
    // DO NOT call FService.ProcessRequests() in this thread!
  end;
end;
 
end.


--
Remy Lebeau (TeamB)
Flavio Redi

Posts: 4
Registered: 11/3/14
Re: Problems with Windows Service in XE7  
Click to report abuse...   Click to reply to this thread Reply
  Posted: Oct 15, 2015 5:51 AM   in response to: Remy Lebeau (Te... in response to: Remy Lebeau (Te...
Remy Lebeau (TeamB) wrote:
Flavio wrote:

I tryied to switch to thread, but the error still remains.

In your OnStop event handler, you are setting the Stopped parameter to False
instead of True. As such, the service is not actually stopping.

TService automatically sets its Status property to csStopPending before calling
OnStop, and automatically sets its Status to csStopped if OnStop returns
Stopped=True, but it does not automatically reset the Status back to csRunning
if OnStop returns with Stopped=False. Also, you need to report the current
Status periodically to the SCM while waiting for your worker thread to terminate.

So, in this case, the SCM ends up timing out waiting for a status change
and reports an error because it thinks your service failed to stop correctly
(which is true).

Try this instead:

interface
 
uses
  Classes, SvcMgr;
 
type
  TsvcTeste = class(TService)
    procedure ServiceStop(Sender: TService; var Stopped: Boolean);
    procedure ServiceStart(Sender: TService; var Started: Boolean);
    procedure ServiceShutdown(Sender: TService);
  private
    { Private declarations }
    FThread: TThread;
  public
    function GetServiceController: TServiceController; override;
    { Public declarations }
  end;
 
var
  svcTeste: TsvcTeste;
 
implementation
 
type
  TTestThread = class(TThread)
  private
    FService: TsvcTeste;
    { Private declarations }
  protected
    procedure Execute; override;
  public
    constructor Create(AService: TsvcTeste); reintroduce;
    property Service: TsvcTeste read FService;
  end;
 
procedure ServiceController(CtrlCode: DWord); stdcall;
begin
  svcTeste.Controller(CtrlCode);
end;
 
function TsvcTeste.GetServiceController: TServiceController;
begin
  Result := ServiceController;
end;
 
procedure TsvcTeste.ServiceStart(Sender: TService; var Started: Boolean);
begin
  FThread := TTestThread.Create(Self);
  Started := True;
end;
 
procedure TsvcTeste.ServiceStop(Sender: TService; var Stopped: Boolean);
begin
  ServiceShutdown(Sender);
  Stopped := True;
end;
 
procedure TsvcTeste.ServiceShutdown(Sender: TService);
begin
  if FThread <> nil then
  begin
    FThread.Terminate;
 
    // TThread.WaitFor() blocks until the thread is terminated, but the service's
    // current status (csStopPending) needs to be reported periodically so 
the SCM
    // does not time out...
 
    //FThread.WaitFor;
    while WaitForSingleObject(FThread.Handle, Self.WaitHint-10) = WAIT_TIMEOUT 
do
      Self.ReportStatus;
 
    FreeAndNil(FThread;
  end;
end;
 
constructor TTestThread.Create(AService: TsvcTeste);
begin
  inherited Create(False);
  FService := AService;
end;
 
procedure TTestThread.Execute;
begin
  while not Terminated do
  begin
    // do some work...
    Sleep(1000);
 
    // DO NOT call FService.ProcessRequests() in this thread!
  end;
end;
 
end.


--
Remy Lebeau (TeamB)

I had set this Stopped to False as a test and I forgot to set it to True again. But with the code in ServiceShutdown now all is working normally. Thank you so much.
Legend
Helpful Answer (5 pts)
Correct Answer (10 pts)

Server Response from: ETNAJIVE02