Newsgroups : Borland : borland.public.delphi.internet.winsock : 2006 May : Re: Delphi 2005 Personal and Indy 10.0.75: Indy don't work!!!

www.cryer.info
Managed Newsgroup Archive

Re: Delphi 2005 Personal and Indy 10.0.75: Indy don't work!!!

Subject:Re: Delphi 2005 Personal and Indy 10.0.75: Indy don't work!!!
Posted by:"Remy Lebeau (TeamB)" (no.spam@no.spam.com)
Date:Fri, 2 Jun 2006 17:02:07

"Jamie Dale" <j.dale@turboz.net> wrote in message
news:4480be89@newsgroups.borland.com...

> Check out the online service tutorials - they nearly all use a timer
> to log the diskspace every 5 mins etc etc.

Then they are all doing the wrong thing.

> Whats wrong with using a timer anyway? (just for curiousitys sake)

I am assuming that you are using TTimer, which is a message-based timer.
The WM_TIMER message is posted to the message queue of the thread that
creates the TTimer instance.  TService is instantiated in the main thread,
so the TTimer would be running off of the main thread message queue.
TService creates a thread internally for its work.  That means that the
TTimer is running in a different thread than the TService is running.  If
the TTimer accesses members of the TService, then you have a race condition
unless you protect access to all of the members with a mutex, semaphore, or
critical section.  You also have race condition due to the main thread and
TService worker thread accessing the TTimer during startup and shutdown.

> there are even fewer ways of debugging services :*(

A service can be debugged the same way a non-service application can.
Borland's debugger works just fine for services.  There is only 1 difference
between debugging a service and debugging an application,and that is in
regards to how the debugger finds the process being debugged.

For an application, you can simply press F8 or F9 and the IDE will launch
the application .exe file and attach the debugger to the new process
automatically.

You can't do that with a service.  You have to start the service with the
SCM first, and then attach the debugger to the service manually using the
debugger's "Attach to Process" feature.  Once the debugger is attached to
the service's process, press F9 to continue execution and you can then debug
the code normally like any other project.

The only tricky part is when you need to debug the service's startup code.
For that, you need to increase the service's WaitHint property (I generally
use 30-45 seconds) and then put a Sleep() at the very beginning of the
TService's OnStart event hander for the duration of the WaitHint.  While the
service is sleeping, the WaitHint property told the SCM not to expect a
quick startup, so it won't error when the service takes awhile to start.
This way, this gives you enough time to switch over to the IDE and attach
the debugger before the sleeping finishes.  For example:

    procedure TService1.ServiceCreate(Sender: TObject);
    begin
        {$IFDEF DEBUG}
        WaitHint := 30000;
        {$ENDIF}
    end;

    procedure TService1.ServiceStart(Sender: TService; var Started:
Boolean);
    begin
        {$IFDEF DEBUG}
        Sleep(WaitHint-100);
        ReportStatus; // so the SCM waits another WaitHint interval
        {$ENDIF}

        // Your normal startup code here.  Put a breakpoint somewhere
        // so that the debugger has a place to stop after the sleeping
finishes
    end;

> wanna come round my place and take a look?

I doubt that would work, considering that you are on the other side of the
globe from me.

> True, but then look at no-ip.com - they're dynamic DNS updater
> can be run as a service with a GUI so I figured, why not?

For a single executable file to do that reliably, it would hae to separate
the service and non-service logics, and then decide at runtime which one to
invoke at startup.  A service executable can have a separate GUI implemented
that runs in a separate process.  I tend to do that in my own services to
provide setup UIs in the same file as the service that is being configured.
At runtime, command-line "/service" and "/setup" paramaters are used so the
executable knows which mode to run in.

> I did experiment with passing data from one application to another
> but it didn't always seem to be successful

Some communication technique, such as window messages, do not work with
services because they usually run on a different workstation then the one
the user is interacting with.  Messages can't pass between workstations.
There are other kinds of communications that will, though.  For simple
things, you can use ControlService() to send custom SCM messages to the
service directly, and have the TService override its virtual
DoCustomControl() method.  Alternatively, you can use TCP sockets or named
pipes.  These work especially well in services.

> I kinda find it easier to use TIdTCPClient/Server these days but
> then that has its pitfalls...

Those work well in services as well.

> And under the System account they can.

Not if there are GUI resources attached to the service, they can't.  Not
very well, anyway.

> Talker.exe (which I told you about previously) can speak
> with no user logged on at all.

That has no relavance to what I've been talking about.

> But Talker.exe has worked faultlessly for over 6 months - almost
> 7!!! - Until now!

That doesn't require a GUI to do its work, though.   You said yourself that
Talker is using DirectX to do its speaking.  DirectX doesn't require a user
to be logged in to function.

> The "Build with runtime packages" box is NOT checked.

Did you also uncheck the "Use Dynamic RTL" option?  If not, then the
executables will be dependant on external DLLs for memory management.
Perhaps you are getting corrupted memory due to an incompatibilty between
the D6 VCL and the D2005 memory manager?

> I have successfully used it in a service for the last 6 months with
> no faults at all. Though I imported the ActiveX control and used
> the DirectSS component on my form.

DirectSS has nothing to do with MSAgent.  They are separate and independant
technologies.

> I know you mean well but I've got first hand experience using it.

And I have first-hand experience writing services without the use of
third-party wrappers.  And I know the pitfalls that services can have at the
OS and VCL levels.

> if you set the forms visible to false, (if it's running as a service) then
you
> can avoid all the complexities of GUI's trying to show up while no user
> is logged on etc etc.

That does not change what I said.  An invisible form still allocates and
binds to resources that can disappear behind the form's back during a user
logout, and when the user logs back in the form will be corrupted because
its resources are invalid.

> Remember if the form was visible hell would break loose which is why
> I only set it visible if it is NOT a service. There is also a menu item so
> that if a user is logged on, they see a tray icon.

Only an Interactive service can access the System Tray to place icons.
Which means the service won't work properly when no Interative user is
logged in.  That is another thing that is best moved into a non-service
application that runs while the user is logged in.  The service itself
should not be trying to display tray icons at all.

> Not had that happen yet to be honest. Maybe there are some
> differences with XP & NT?

Nope.  This effects all versions from NT up to and including Server 2003

> Either way it runs under the system account so effectively, the
> user never logs off but is always logged on. That makes sense?

You do know how dangerous it is to running your services under the SYSTEM
account, don't you?  It is not that difficult for malicious software to
cause a fault in another process, such as a service, and gain permissions to
the machine.  It is generally best practice to create a new user account
with the minimal permissions needed and then run the service under that
account instead.


Gambit

Replies:

In response to:

www.cryer.info
Managed Newsgroup Archive