Board index » cppbuilder » using application Service wih access to Database

using application Service wih access to Database


2005-07-13 05:16:05 AM
cppbuilder15
I'm using c++Builder 5 under windows xp and I want to create an application
Service So I have creatd it , put a ttimer object , a TDatabase object and a
TTable object in the service object
I wrote the few lines of code
Service1::OnExecute
{
while (!Terminated)
{Service1->ProcessRequest(true);
};
}
Service1::BeforeInsatll
{
Database1->Connected=true;
}
Timer1::OnTimer
{
Beep();
TTable1->Connected=false;
Ttable1->Connected=true;
TTable1->Connected=false;
}
what happen?
When I 'mrunning my project (Project /install) the program runs well until I
clik on the OK Butoon.
When I start the service from the service command panel , it runs one time
and there is nothing after; when I stop it I get a mistake (impossible
d'éxécuter le scripte : unable to process the script etc..)
When I uninstall my application service it runs well until I click on the Ok
Buttton
I don't understand what happens does anybody can help me?
I 've wrote the same program under delphi and I don't have these mistake?
Is it a bug from c++Builder ; it seems that the handle to the databse isn't
recognize ;
 
 

Re:using application Service wih access to Database

"Didier" < XXXX@XXXXX.COM >wrote in message
Quote
Service1::OnExecute
{
while (!Terminated)
{Service1->ProcessRequest(true);
};
}
Get rid of that. TService already handles SCM requets just fine without any
OnExecute event handler assigned.
Quote
Service1::BeforeInsatll
{
Database1->Connected=true;
}
That is not correct. Use the OnStart event instead.
Quote
When I start the service from the service command panel , it runs
one time and there is nothing after; when I stop it I get a mistake
(impossible d'éxécuter le scripte : unable to process the script etc..)
You are not handling the service properly in the first place, so it makes
sense that things would not work as expected.
Gambit
 

Re:using application Service wih access to Database

Thank you Gambit for your help but it doesn't solve my case !
I've tried to put the code written in the beforeinstall method into the
onstart and it doesn't change anything
I' m very anxious because I don't see any solution
I've written exactly the same program under delphi 5 and it runs very well
Why??
I've joined the entire code It's very short
C++BUilder code
//---------------------------------------------------------------------------
#ifndef Unit1H
#define Unit1H
//---------------------------------------------------------------------------
#include <SysUtils.hpp>
#include <Classes.hpp>
#include <SvcMgr.hpp>
#include <vcl.h>
#include <Db.hpp>
#include <DBTables.hpp>
#include <ExtCtrls.hpp>
//---------------------------------------------------------------------------
class TService1 : public TService
{
__published: // Composants gérés par l'EDI
TTimer *Timer1;
TDatabase *Database1;
TTable *Table1;
void __fastcall Timer1Timer(TObject *Sender);
void __fastcall ServiceBeforeInstall(TService *Sender);
private: // Déclarations utilisateur
public: // Déclarations utilisateur
__fastcall TService1(TComponent* Owner);
TServiceController __fastcall GetServiceController(void);
friend void __stdcall ServiceController(unsigned CtrlCode);
};
//---------------------------------------------------------------------------
extern PACKAGE TService1 *Service1;
//---------------------------------------------------------------------------
#endif
//---------------------------------------------------------------------------
#include "Unit1.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TService1 *Service1;
//---------------------------------------------------------------------------
__fastcall TService1::TService1(TComponent* Owner)
: TService(Owner)
{
}
TServiceController __fastcall TService1::GetServiceController(void)
{
return (TServiceController) ServiceController;
}
void __stdcall ServiceController(unsigned CtrlCode)
{
Service1->Controller(CtrlCode);
}
//---------------------------------------------------------------------------
void __fastcall TService1::Timer1Timer(TObject *Sender)
{
Beep();
Table1->Active=false;
Table1->Active=true;
Table1->Active=false;
}
//---------------------------------------------------------------------------
void __fastcall TService1::ServiceBeforeInstall(TService *Sender)
{
Database1->Connected=true;
}
//---------------------------------------------------------------------------
Delphi Code
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, SvcMgr, Dialogs,
ExtCtrls, Db, DBTables;
type
TService1 = class(TService)
Timer1: TTimer;
Database1: TDatabase;
Config: TTable;
procedure Timer1Timer(Sender: TObject);
procedure ServiceBeforeInstall(Sender: TService);
private
{ Déclarations privées }
public
function GetServiceController: TServiceController; override;
{ Déclarations publiques }
end;
var
Service1: TService1;
implementation
{$R *.DFM}
procedure ServiceController(CtrlCode: DWord); stdcall;
begin
Service1.Controller(CtrlCode);
end;
function TService1.GetServiceController: TServiceController;
begin
Result := ServiceController;
end;
procedure TService1.Timer1Timer(Sender: TObject);
begin
Beep;
Config.Active:=false;
Config.Active:=true;
Config.Active:=false;
end;
procedure TService1.ServiceBeforeInstall(Sender: TService);
begin
Database1.Connected := true ;
end;
end.
"Remy Lebeau (TeamB)" < XXXX@XXXXX.COM >a écrit dans le message de news:
XXXX@XXXXX.COM ...
Quote

"Didier" < XXXX@XXXXX.COM >wrote in message
news: XXXX@XXXXX.COM ...

>Service1::OnExecute
>{
>while (!Terminated)
>{Service1->ProcessRequest(true);
>};
>}

Get rid of that. TService already handles SCM requets just fine without
any
OnExecute event handler assigned.

>Service1::BeforeInsatll
>{
>Database1->Connected=true;
>}

That is not correct. Use the OnStart event instead.

>When I start the service from the service command panel , it runs
>one time and there is nothing after; when I stop it I get a mistake
>(impossible d'éxécuter le scripte : unable to process the script etc..)

You are not handling the service properly in the first place, so it makes
sense that things would not work as expected.


Gambit


 

{smallsort}

Re:using application Service wih access to Database

I've seen on the borland support site one article [1503] very interesting
(c++Builder->errors look for service) from which I extract thes lines
what do you think about this? it seems to be my problem because I use an
interbase database and the server interbase is on the same machine that the
application Service !! (i'm working under windows xp) but I think that is
the same thing
Problem:
If you attempt to access an Interbase database from within an NT Service App
where the NT Service App runs on the same machine as the Interbase server,
you will not be able to connect to the database unless the Delphi NT app is
configured properly and the BDE alias is configured properly. This is also
true if the NT Service app is running on a different computer from the
Interbase server (as in Client/Server mode). The NT Service app must be able
to run when the desktop is logged off.
Solution:
The information in this article applies to:
** InterBase 5.x
** Windows NT 4.0
Scope :
This problem affects anyone writing an NT Service App which accesses an
Interbase database. I suspect the same problem will occur if you attempt to
access an Interbase database from a DCOM server app or a process invoked by
the NT scheduler service. In order to have the NT Service App running with
InterBase
Server, the following configurations are needed:
BDE Alias :
The BDE alias MUST have the SERVER NAME set to be "servermachine:drive:path"
Example - zeus003:C:Delphi4ProjectsMichelinPOCSocketData.gdb
Tdatabase component :
The Tdatabase component in the Delphi app MUST use the BDE alias. I have not
tested all permutations but I do know that only using the following
parameter
overrides works :
USER NAME=SYSDBA
PASSWORD=masterkey
Have prompt for login turned off.
You MUST not have a SERVER NAME=path as a parameter override.
Services :
Interbase Guardian - Log On As : SYSTEM and interact with desktop
Interbase Server - Log On As : SYSTEM and interact with desktop
Your NT Service App - Log On As : SYSTEM and DO NOT interact with desktop
Caveat :
I know this works if you have TCP/IP as the only protocol configured on the
machine. The hint from the Interbase engineer was that the communication to
the Interbase server must be made over TCP/IP for this solution to work.
Adding other protocols or substituting TCP/IP was not tested by me.
Source by:
Mike Carroll
Maritime
--
Didier BODINIER
Service Développement
AEROPRODUCT
Rue du 11 Novembre
44110 SOUDAN
Tél. direct : (+33).02.40.28.51.94
Fax : (+33). 02.40.28.53.87
Mail : XXXX@XXXXX.COM
 

Re:using application Service wih access to Database

"Didier" < XXXX@XXXXX.COM >wrote in message
Quote
Thank you Gambit for your help but it doesn't solve my case !
You never did explain EXACTLY what was actually happening. What is likely
happening is that your code is throwing an unhandled exception that is
terminating the service prematurely.
Have you tried debugging the service yet? Place a Sleep() at the beginning
of the OnStart event, and increase the WaitHint property. Then start the
service and use the de{*word*81}'s "Attach to Process" option. The Sleep() is
used to ensure that the service waits a sufficient amount of time for you to
attach the de{*word*81} before it then begins doing its work.
Gambit
 

Re:using application Service wih access to Database

"Didier" < XXXX@XXXXX.COM >wrote in message
Quote
I've seen on the borland support site one article [1503] very interesting
(c++Builder->errors look for service) from which I extract thes lines

what do you think about this?
I think the article is correct. You must use TCP/IP as the communications
layer if you want to access Interbase from a service. TCP/IP is not subject
os the OS's security model, whereas other communication layers are, such as
named pipes. Services are subject to user security rights like any other
application, but more so since they can run outside of any user account and
thus are also subject to the OS's own access rights as well, which are quote
strict. In particular, services cannot access the network by default, which
is likely the root cause of your problem.
Gambit
 

Re:using application Service wih access to Database

I'm sorry but I thought my program run well under delphi but it didnn't (I
've placed beep instruction at the beginning of the timer interrupt ; by
placing at the end behind the Table1->active=true , i see that my program
doesn't run , there is an unhandled exception that shor-circuited dthe end
of the interrupttimer method)
Now I try to understand how to open a database in an application
Service;this is why I 've this exception.
how I've proceeded
1? I've created a new application Service
2? I've place in the Tservice sheet a TDatabe Object, a Timer and a TTable.
3? I put the Timer interval to 3000
4? I've written the OnExecute Method ot the Tservice Object
While(!Terminated)
{
ServiceThread->ProcessRequest(true);
}
5? I 've writtenthe AfterInsall Methhod
{
database1->Connected=true;
}
6? then I 've written a timer interrupt to know if my program runs
{
Table1->Active=false;
Table1->Active=true;
Table1->active=false;
Beep();
}
that 's all I've done
I don't understand what you explain
Do I 've to delete the code in the onexecute method?
I've trie to put the same code as in the afterinstall method in the onstart
method and it has changed nothing
the proble is that I can acces the database and Idon't know why!!
 

Re:using application Service wih access to Database

"Didier" < XXXX@XXXXX.COM >wrote in message
Quote
4? I've written the OnExecute Method ot the Tservice Object
As I already suggested to you earlier, get rid of that code. You do not
need it at all.
Quote
5? I 've writtenthe AfterInsall Methhod
{
database1->Connected=true;
}
Again, you are NOT using the proper events. Begin/AfterInstall are NOT
triggered when the service is actually run. You should be using the OnStart
event to activate your database, and the OnStop/Shutdown events to close it.
Quote
6? then I 've written a timer interrupt to know if my program runs
{
Table1->Active=false;
Table1->Active=true;
Table1->active=false;
Beep();
}
Why do you close, reopen, and reclose the database each time the timer is
triggered?
Quote
I don't understand what you explain
What exactly don't you understand?
Quote
Do I 've to delete the code in the onexecute method?
Yes. You should not be using the OnExecute event at all. If you need your
service is perform operations while it is running, you should place them
into a separate thread that is spawned in the OnStart event and terminated
in the OnStop/Shutdown events.
Quote
I've trie to put the same code as in the afterinstall method in
the onstart method and it has changed nothing
See my comments above.
Quote
the proble is that I can acces the database and Idon't know why!!
Because you are not using it properly in the first place!
Gambit
 

Re:using application Service wih access to Database

ok I've done what, you suggested to me
1?) I've delete th code in the OnExecutte method
2? I 've added this code in the onstart method
if (!Dtaabase1->connected) then
{
Database1->Connected=true;
}
3? I've adde this code in the OnStop method
Database1->Connected=false;
Now I've had to say you that my code
Table1->active=false;
Table1->Active=true;
Table1->active=false
Beep()
is placed to know firstly that all commands are executed in the timer
interrupt and secondary that I can access to the tables of my database
finally I run the program and when I start it I get the next message:
"Le service aa_delphi sur Ordinateur local a démarr?puis s'est
arrêt?Certains service peuvent s'arrêter automatiquement s'ils n'ont aucune
tâche ?effectuer,par exemple,le service des alertes et les journaux de
performance"
I want my service runs continuously(loop) because he has a method to do in
the timerinterrupt
thank you again for your help
 

Re:using application Service wih access to Database

"Didier" < XXXX@XXXXX.COM >wrote in message
Quote
finally I run the program and when I start it I get the next message:
"Le service aa_delphi sur Ordinateur local a démarr?puis s'est
arrêt?Certains service peuvent s'arrêter automatiquement s'ils n'ont
aucune tâche ?effectuer,par exemple,le service des alertes et les
journaux de performance"
Please always provide English translations of messages.
If I translated that correctly, it is basically warning you that the service
stopped itself immediately after starting. Which probably goes back to your
code throwing unhandled exceptions. Again, did you try debugging the
project yet to find out what is actualy happening?
Quote
I want my service runs continuously(loop) because he has a method
to do in the timerinterrupt
Again, I suggest you look at using a worker thread instead of a timer.
Gambit
 

Re:using application Service wih access to Database

Sorry I've forgot
here is the translation
The service aa_delphi on the local computer has started then stopped.Some
services can stop automatically if they have no task to do; for example
service of alerts or performances record
 

Re:using application Service wih access to Database

"Didier" < XXXX@XXXXX.COM >wrote in message
Quote
Sorry I've forgot
here is the translation
Like I said, something in your code is terminating the service prematurely,
most likely an unhandled exception.
Gambit
 

Re:using application Service wih access to Database

here is the code (OnSart method from the Tservice)but the rpoble is alway
the same I can't connect to my database:
this code fails
if (!Database1->Connected )
{
// try
{
Database1->Connected = true ;
}
// catch(...){}
}
this code is Ok:
if (!Database1->Connected )
{
try
{
Database1->Connected = true ;
}
catch(...){}
So the problem is that I can't connect to my database but why?
In conception if I put the propriety connected of the database object to
true there is no problem so The Tdatabase object is correctly writtem
(password,user name etc...)
 

Re:using application Service wih access to Database

"Didier" < XXXX@XXXXX.COM >wrote in message
Quote
here is the code (OnSart method from the Tservice)but the
rpoble is alway the same I can't connect to my database:
Once again, I ask you to PLEASE run your code in the de{*word*81} to find out
EXACTLY what is actually happening.
Quote
this code fails
<snip>
this code is Ok:
All the more reason to debug your code. It is indeed throughing an
exception. You need to find out what exception is actually being thrown.
Gambit
 

Re:using application Service wih access to Database

I think that I 'm clear and the instruction Database1->connected=true is the
problem ; it makes an exception
Now I'd like to know how to debug application Service;if I run it in the
Ide, it stops after about 500 Ms so I can start my service with the panel
configuration .is there anything I don't do correctly?