Board index » delphi » NT Service exposing Automation interface -- how?

NT Service exposing Automation interface -- how?

Folks:

Anyone seen a sample of an NT Service that exposes an Automation
interface that can be connected to via GetActiveObject?

The idea is to have a desktop app able to communicate with the
service. The advice everywhere is "just use some form of interprocess
communication" -- where none of those methods are exactly well-beaten
paths.

So it seemed like it ought be not too hard to do this with Automation.

So far I have demoed the following:

a) Trivial service that can install and just sit there, start, stop etc.

b) Regular application with Automation server and client
that can exchange data.

c) I even created a service containing automation object, install,
register etc... plus set the ServiceStartName and Password so that
a desktop app is permitted to talk to it via Automation,
(using CoMyServerObj.Create) and this sorta works except after 5-10
secs I get COM server error dialog and it stops.

d) But it looks like what I really want is to create an object and
register
in ROT so that desktop app can call GetActiveObject (per Binh Li's
excellent
article pertaiing to regular app).  Tried that approach, but all
attempts to start service fail, first giving an error regarding
CoInitialize (so I added that), now with a meaningless error.

Anyhow, I feel a bit like I'm shooting in the dark -- that's a section
of
code it's hard to debug. What I could really use is a sample that covers
this
ground:

-- NT Service
-- Automation Interface

Anyhow, as I say, any pointers greatly appreciated!

TIA

Graham

--------------------------------------------
Graham Wideman
MS MVP for Visio
Books:
Visio 2000 Developer's Survival Guide
Visio 2002 Developer's Survival Pack (with Tools)
... and resources for programmable diagramming at:
http://www.diagramantics.com

 

Re:NT Service exposing Automation interface -- how?


Graham Wideman, Visio MVP wrote:

Quote
> Anyone seen a sample of an NT Service that exposes an Automation
> interface that can be connected to via GetActiveObject?

> The idea is to have a desktop app able to communicate with the
> service. The advice everywhere is "just use some form of interprocess
> communication" -- where none of those methods are exactly well-beaten
> paths.

I just had nightmares with this.  I did it a bit differently though -
instead of registering a single object in the ROT, I allowed each client to
create it's own object, with all of the objects accessing the same
underlying data structure in the service.

Also, my service had to work in a particular way:

1.  I didn't want the client application to be able to start the service
with DCOM.  That's because the clients would be in 300 separate locations
talking to a central server - and if I'd deliberatly stopped the service
for maintenance I didn't want a client somewhere trying to start it.

2.  Because the clients had to be installed through a simple batch file, I
couldn't call use DCOMCNFG - so I had to call CoInitializeSecurity on both
the client and server.

Here's what I did:

I wrote a TServiceAutoObjectFactory class derived from TAutoObjectFactory,
and overrode UpdateRegistry to do the following things.  (UpdateRegistry is
called (indirectly) by SvcMgr.Application.Initialize, and because it's
called after CoInitialize, but before any other com stuff, it's a good
place to call things like CoInitializeSecurity).

1.  If the command line parameter was -Install or -Uninstall, the service
was simply being installed, and no COM stuff should be done.  Simply call
Application.Run (so that the  SvcMgr installs the service), and halt.

2.  If the command line parameter was -RegServer or -Server , call
CoInitializeSecurity (see below) and install the com objects by calling
inherited UpdateRegistry, and RegisterAsService to that DCOM.  You'd need
to call it like this on the client computers - which don't need the service,
 but still need the registry entries so that CoYourControl.CreateRemote
works.

3.  If there are no command line parameters, the .exe is probably being
started by the service control manager.  It should call
CoInitializeSecurity, inherited UpdateRegistry amnd RegisterAsService.

When you call CoInitializeSecurity on the server, you need to pass a
security decriptor containing the owner and group SIDS for the current
process or thread's token.  It's a bit tricky so let me know if you want
some sample code.

On the client end, simply call CoInitialize and CoInitializeSecurity in the
main form's OnCreate method - like this:

  CoInitialize (nil);
  OleCheck (CoInitializeSecurity(nil, -1, Nil, nil, RPC_C_AUTHN_LEVEL_NONE,
RPC_C_IMP_LEVEL_IMPERSONATE, nil, Integer (EOAC_NONE), nil));

It worked fine in W2K and XP Pro :

*  If you try to start the client when the service isn't running, it says
'class not registered' - because it's not!
*  If you start the client when the service is running, from whatever
remote computer, (or the local one) it connects!

*** HOWEVER ***  I couldn't get the wretched thing working on NT4!  If the
service was running and I ran the client, DCOM would start another instance
of the .exe running - despite the AppID registry stuff, LocalService value,
all being correctly set..   The only way I could get it to work was to have
DCOM start the service.  Then the client(s) would connect fine - all to the
same instance of the .EXE - but it wasn't how I wanted it to work.   I
spent days trawling through registry keys in HKEY_CLASSES_ROOT.  I spent
days crawling through an MFC ATL service that did the same thing at startup
(and which works!)  I spent days examining all the DCOM security issues,
using DCOMCNFG to totally relax security, etc. etc. etc.

In the end - with the deadline looming I rewrote the data transport layer
to use named pipes instead of DCOM.

Colin
e-mail :co...@wilsonc.demon.co.uk
web: http://www.wilsonc.demon.co.uk/delphi.htm

Posted with XanaNews

Re:NT Service exposing Automation interface -- how?


Colin:

Thanks for your detailed discussion. I actually was not interested
in doing DCOM, just COM to allow communication to a "front-panel"
app running on same box.

Anyhow, your tale was interesting, except you got stuck. I had
already looked into named pipes, and now they're even more looking
like the way to go!

Graham

--------------------------------------------
Graham Wideman
MS MVP for Visio
Books:
Visio 2000 Developer's Survival Guide
Visio 2002 Developer's Survival Pack (with Tools)
... and resources for programmable diagramming at:
http://www.diagramantics.com

Other Threads