By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
457,728 Members | 1,145 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 457,728 IT Pros & Developers. It's quick & easy.

C# Service Terminating Itself

P: n/a
I have a C# Windows Service running as the NetworkService account because it
needs to access a network share.

As part of the service's initialization, I want the service to terminate, if
an unrecoverable error occurs. When that case occurs, I create a
ServiceController object and call the Stop() method.

However - I get an exception thrown saying access denied. If I switch to
using the LocalService account it works fine, but I lose access to my
network resources.

What is the proper way for a service to stop itself? I would really rather
not add a separate user account to accomplish this. It seems kind of odd
that a service cannot stop itself.
Any ideas?

--
Adam Clauss

Nov 17 '05 #1
Share this Question
Share on Google+
23 Replies


P: n/a
> However - I get an exception thrown saying access denied. If I switch to
using the LocalService account it works fine, but I lose access to my
network resources.
Looks like LocalService has rights to stop services, but NetworkService
does not. Sounds logical enough: the method you use can be used to stop
any service, not just itself.
What is the proper way for a service to stop itself? I would really
rather
not add a separate user account to accomplish this. It seems kind of odd
that a service cannot stop itself.
Any ideas?

Did you try Application.Exit() ?

Greetings,
Wessel
Nov 17 '05 #2

P: n/a
"Wessel Troost" <no*****@like.the.sun> wrote in message
news:op.st9qu6xaf3yrl7@asbel...
However - I get an exception thrown saying access denied. If I switch to
using the LocalService account it works fine, but I lose access to my
network resources.
Looks like LocalService has rights to stop services, but NetworkService
does not. Sounds logical enough: the method you use can be used to stop
any service, not just itself.
What is the proper way for a service to stop itself? I would really
rather
not add a separate user account to accomplish this. It seems kind of odd
that a service cannot stop itself.
Any ideas?

Did you try Application.Exit() ?


Would be great, but that only exists in a Windows.Forms context.

--
Adam Clauss

Greetings,
Wessel

Nov 17 '05 #3

P: n/a
Initialize your service in OnStart and throw an exception if it fails.
Throwing an exception will terminate the service, report an error to the SCM
and automatically log the exception message in the Application log.

Willy.

"Adam Clauss" <ca*****@tamu.edu> wrote in message
news:11*************@corp.supernews.com...
"Wessel Troost" <no*****@like.the.sun> wrote in message
news:op.st9qu6xaf3yrl7@asbel...
However - I get an exception thrown saying access denied. If I switch
to
using the LocalService account it works fine, but I lose access to my
network resources.

Looks like LocalService has rights to stop services, but NetworkService
does not. Sounds logical enough: the method you use can be used to stop
any service, not just itself.
What is the proper way for a service to stop itself? I would really
rather
not add a separate user account to accomplish this. It seems kind of
odd
that a service cannot stop itself.
Any ideas?

Did you try Application.Exit() ?


Would be great, but that only exists in a Windows.Forms context.

--
Adam Clauss

Greetings,
Wessel


Nov 17 '05 #4

P: n/a
"Willy Denoyette [MVP]" <wi*************@telenet.be> wrote in message
news:uT**************@TK2MSFTNGP09.phx.gbl...
Initialize your service in OnStart and throw an exception if it fails.
Throwing an exception will terminate the service, report an error to the
SCM and automatically log the exception message in the Application log.
Is that considered a "good" way to terminate a service? It's also possible
that sometime down the road (post-initialization) that we may want to
terminate. Unfortunately, "down the road' for our application means from
one of several threads. Throwing an exception here will not actually
terminate the service. Is there a way to end it from there?

It's amazing... I never though I would have trouble trying to END an
application :)

--
Adam Clauss


Willy.

"Adam Clauss" <ca*****@tamu.edu> wrote in message
news:11*************@corp.supernews.com...
"Wessel Troost" <no*****@like.the.sun> wrote in message
news:op.st9qu6xaf3yrl7@asbel...
However - I get an exception thrown saying access denied. If I switch
to
using the LocalService account it works fine, but I lose access to my
network resources.

Looks like LocalService has rights to stop services, but NetworkService
does not. Sounds logical enough: the method you use can be used to stop
any service, not just itself.

What is the proper way for a service to stop itself? I would really
rather
not add a separate user account to accomplish this. It seems kind of
odd
that a service cannot stop itself.
Any ideas?

Did you try Application.Exit() ?


Would be great, but that only exists in a Windows.Forms context.

--
Adam Clauss

Greetings,
Wessel



Nov 17 '05 #5

P: n/a
> Is that considered a "good" way to terminate a service? It's also

What Willy says sounds very good, definitely the way to go.
possible
that sometime down the road (post-initialization) that we may want to
terminate. Unfortunately, "down the road' for our application means from
one of several threads. Throwing an exception here will not actually
terminate the service. Is there a way to end it from there?

Eeh.... maybe this works:

Environment.Exit()

or if you're in a bad mood:

Process.GetCurrentProcess().Kill();

Greetings,
Wessel
Nov 17 '05 #6

P: n/a

"Adam Clauss" <ca*****@tamu.edu> wrote in message
news:11*************@corp.supernews.com...
"Willy Denoyette [MVP]" <wi*************@telenet.be> wrote in message
news:uT**************@TK2MSFTNGP09.phx.gbl...
Initialize your service in OnStart and throw an exception if it fails.
Throwing an exception will terminate the service, report an error to the
SCM and automatically log the exception message in the Application log.


Is that considered a "good" way to terminate a service? It's also
possible that sometime down the road (post-initialization) that we may
want to terminate. Unfortunately, "down the road' for our application
means from one of several threads. Throwing an exception here will not
actually terminate the service. Is there a way to end it from there?


No it isn't, you aren't terminating a "running" service, for the SCM, the
service is considered to be "started" once the OnStart() has returned
successfully, you throw an exception which indicates to the SCM that the
service failed to start.
A clean way to stop a "running" Service, is by asking the SCM to issue a
Stop request (using the ServiceControler object for instance), but you need
to do this from an external program that has sufficient privileges to do so.
The external program (lets name it the controller) should set-up an IPC
channel (using remoting or whatever) over which the Service can communicate
it's internal statuses and request actions from the controller.

Willy.

Nov 17 '05 #7

P: n/a

"Wessel Troost" <no*****@like.the.sun> wrote in message
news:op.st9urwk4f3yrl7@asbel...
Is that considered a "good" way to terminate a service? It's also


What Willy says sounds very good, definitely the way to go.
possible
that sometime down the road (post-initialization) that we may want to
terminate. Unfortunately, "down the road' for our application means from
one of several threads. Throwing an exception here will not actually
terminate the service. Is there a way to end it from there?

Eeh.... maybe this works:

Environment.Exit()

or if you're in a bad mood:

Process.GetCurrentProcess().Kill();

Greetings,
Wessel


Wessel,

This is something you should avoid, the reason is simple, the Service
Control Manager is the master of the game and he doesn't like someone else
is playing with it's toys, so when you kill a process that happens to be a
service you are effectively disturbing the SCM and possibly corrupting it's
DB state.
How many times did you see messages like "Service cannot be started because
it's already running" while in reality it's not?

Willy.

Nov 17 '05 #8

P: n/a
"Willy Denoyette [MVP]" <wi*************@telenet.be> wrote in message
news:u6*************@TK2MSFTNGP15.phx.gbl...
Environment.Exit()

or if you're in a bad mood:

Process.GetCurrentProcess().Kill();

Greetings,
Wessel


Wessel,

This is something you should avoid, the reason is simple, the Service
Control Manager is the master of the game and he doesn't like someone else
is playing with it's toys, so when you kill a process that happens to be a
service you are effectively disturbing the SCM and possibly corrupting
it's DB state.
How many times did you see messages like "Service cannot be started
because it's already running" while in reality it's not?


Thats why I was afraid of using the Exception initially. Thought it might
cause a similar situation.

--
Adam Clauss
Nov 17 '05 #9

P: n/a
"Willy Denoyette [MVP]" <wi*************@telenet.be> wrote in message
news:OJ**************@tk2msftngp13.phx.gbl...

"Adam Clauss" <ca*****@tamu.edu> wrote in message
news:11*************@corp.supernews.com...
"Willy Denoyette [MVP]" <wi*************@telenet.be> wrote in message
news:uT**************@TK2MSFTNGP09.phx.gbl...
Initialize your service in OnStart and throw an exception if it fails.
Throwing an exception will terminate the service, report an error to the
SCM and automatically log the exception message in the Application log.


Is that considered a "good" way to terminate a service? It's also
possible that sometime down the road (post-initialization) that we may
want to terminate. Unfortunately, "down the road' for our application
means from one of several threads. Throwing an exception here will not
actually terminate the service. Is there a way to end it from there?


No it isn't, you aren't terminating a "running" service, for the SCM, the
service is considered to be "started" once the OnStart() has returned
successfully, you throw an exception which indicates to the SCM that the
service failed to start.
A clean way to stop a "running" Service, is by asking the SCM to issue a
Stop request (using the ServiceControler object for instance), but you
need to do this from an external program that has sufficient privileges to
do so. The external program (lets name it the controller) should set-up an
IPC channel (using remoting or whatever) over which the Service can
communicate it's internal statuses and request actions from the
controller.


Hehe, what's interesting is that we may already have such a thing, but I've
been told I cannot "expect" it to necessarily be present (clients may elect
whether or not to use this other service).

It looks like given the constraints of the project, I may have to actually
set it up to run as a user account (rather than Network Service). It's the
only way to satisfy all my needs.

Thanks for the help, you've given me some things to think about.

--
Adam Clauss
Nov 17 '05 #10

P: n/a
> A clean way to stop a "running" Service, is by asking the SCM to issue a
Stop request (using the ServiceControler object for instance), but you


In SDK terms, a starting service first calls
RegisterServiceCtrlHandlerEx() to register a callback for communication
with the SCM. When it's running, the service calls
SetServiceStatus(...,SERVICE_RUNNING) to let the SCM know it's up and
running. When it exits, it calls SetServiceStatus(..,SERVICE_STOPPED),
and then exits like a normal program with ExitProcess(). There's no need
for an external program to be involved, from an SDK point of view.

In .NET there appears to be no "natural" way of calling
SetServiceStatus(..,SERVICE_STOPPED). Maybe you could call the function
using P/Invoke. But I'm pretty sure if you just exit the program in some
way, the SCM will find out and set the service status to stopped by itself.

See the service reference in the MSDN:
http://msdn.microsoft.com/library/de..._reference.asp

Greetings,
Wessel
Nov 17 '05 #11

P: n/a
> A clean way to stop a "running" Service, is by asking the SCM to issue a
Stop request (using the ServiceControler object for instance), but you


In SDK terms, a starting service first calls
RegisterServiceCtrlHandlerEx() to register a callback for communication
with the SCM. When it's running, the service calls
SetServiceStatus(...,SERVICE_RUNNING) to let the SCM know it's up and
running. When it exits, it calls SetServiceStatus(..,SERVICE_STOPPED),
and then exits like a normal program with ExitProcess(). There's no need
for an external program to be involved, from an SDK point of view.

In .NET there appears to be no "natural" way of calling
SetServiceStatus(..,SERVICE_STOPPED). Maybe you could call the function
using P/Invoke. But I'm pretty sure if you just exit the program in some
way, the SCM will find out and set the service status to stopped by itself.

See the service reference in the MSDN:
http://msdn.microsoft.com/library/de..._reference.asp

Greetings,
Wessel
Nov 17 '05 #12

P: n/a
Inline

Willy.

"Wessel Troost" <no*****@like.the.sun> wrote in message
news:op.st97xlapf3yrl7@asbel...
A clean way to stop a "running" Service, is by asking the SCM to issue a
Stop request (using the ServiceControler object for instance), but you
In SDK terms, a starting service first calls
RegisterServiceCtrlHandlerEx() to register a callback for communication
with the SCM. When it's running, the service calls
SetServiceStatus(...,SERVICE_RUNNING) to let the SCM know it's up and
running.


Right, RegisterServiceCtrlHandlerEx, that's exactly what's been done in
ServiceBase.ServiceMainCallBack(),
which calls ServiceBase.ServiceMainQueueCallBack() on a worker thread, this
method calls the overriden OnStart() in a try/catch block.
When OnStart returns normally, "StartSuccessful" is written to the EventLog,
and SetServiceStatus() is called with the status set to 4 (SERVICE_RUNNING),
if OnStart throws, the exception message is written to the EventLog as an
Error message prepended with "StartFailed", and SetServiceStatus() is called
with the status set to 1 (SERVICE_STOPPED).
Also note that ServiceBase stuff like OnStart, OnPause etc. runs on the so
called SCM control (unmanaged) thread. This thread is initialized by the
RegisterServiceCtrlHandlerEx(), that's the reason why you shouldn't run any
service code in one of the OnXXX methods, this thread must be able to
receive commands and send timely responses to the SCM each time the SCM
sends a command (this is done over a named pipe channel..

When it exits, it calls SetServiceStatus(..,SERVICE_STOPPED), and then exits like a normal program with ExitProcess().
Not true, the SetServiceStatus is called when OnStop returns, calling
ExitProcess from within a service would be disastrous for processes hosting
multiple services, you don't want to stop all your services hosted in the
same process don't you :-).
There's no need for an external program to be involved, from an SDK point of view.

In .NET there appears to be no "natural" way of calling
SetServiceStatus(..,SERVICE_STOPPED). Maybe you could call the function
using P/Invoke. But I'm pretty sure if you just exit the program in some
way, the SCM will find out and set the service status to stopped by
itself.

Not true, all services must be stoped, started, paused, etc through the
SCM, and this has to be done preferably using an external program (the
reason is obvious right?), samples are the services control panel applet,
and many service controllers running as a foreground program in the system
tray (SQL server manager etc...).
See the service reference in the MSDN:
http://msdn.microsoft.com/library/de..._reference.asp

Greetings,
Wessel

Nov 17 '05 #13

P: n/a
Inline

Willy.

"Wessel Troost" <no*****@like.the.sun> wrote in message
news:op.st97xlapf3yrl7@asbel...
A clean way to stop a "running" Service, is by asking the SCM to issue a
Stop request (using the ServiceControler object for instance), but you
In SDK terms, a starting service first calls
RegisterServiceCtrlHandlerEx() to register a callback for communication
with the SCM. When it's running, the service calls
SetServiceStatus(...,SERVICE_RUNNING) to let the SCM know it's up and
running.


Right, RegisterServiceCtrlHandlerEx, that's exactly what's been done in
ServiceBase.ServiceMainCallBack(),
which calls ServiceBase.ServiceMainQueueCallBack() on a worker thread, this
method calls the overriden OnStart() in a try/catch block.
When OnStart returns normally, "StartSuccessful" is written to the EventLog,
and SetServiceStatus() is called with the status set to 4 (SERVICE_RUNNING),
if OnStart throws, the exception message is written to the EventLog as an
Error message prepended with "StartFailed", and SetServiceStatus() is called
with the status set to 1 (SERVICE_STOPPED).
Also note that ServiceBase stuff like OnStart, OnPause etc. runs on the so
called SCM control (unmanaged) thread. This thread is initialized by the
RegisterServiceCtrlHandlerEx(), that's the reason why you shouldn't run any
service code in one of the OnXXX methods, this thread must be able to
receive commands and send timely responses to the SCM each time the SCM
sends a command (this is done over a named pipe channel..

When it exits, it calls SetServiceStatus(..,SERVICE_STOPPED), and then exits like a normal program with ExitProcess().
Not true, the SetServiceStatus is called when OnStop returns, calling
ExitProcess from within a service would be disastrous for processes hosting
multiple services, you don't want to stop all your services hosted in the
same process don't you :-).
There's no need for an external program to be involved, from an SDK point of view.

In .NET there appears to be no "natural" way of calling
SetServiceStatus(..,SERVICE_STOPPED). Maybe you could call the function
using P/Invoke. But I'm pretty sure if you just exit the program in some
way, the SCM will find out and set the service status to stopped by
itself.

Not true, all services must be stoped, started, paused, etc through the
SCM, and this has to be done preferably using an external program (the
reason is obvious right?), samples are the services control panel applet,
and many service controllers running as a foreground program in the system
tray (SQL server manager etc...).
See the service reference in the MSDN:
http://msdn.microsoft.com/library/de..._reference.asp

Greetings,
Wessel

Nov 17 '05 #14

P: n/a
>> When it exits, it calls SetServiceStatus(..,SERVICE_STOPPED),
and then exits like a normal program with ExitProcess().
Not true, the SetServiceStatus is called when OnStop returns, calling
ExitProcess from within a service would be disastrous for processes
hosting
multiple services, you don't want to stop all your services hosted in the
same process don't you :-).

Every stopping service calls ExitProcess. The other option is the SCM
calling TerminateProcess(), and the SCM doesn't do that, obviously. A
third option would be to generate a Win32 Structured Exception (f.e.
segfault) to leave the process.

If there are multiple services in a process, the process would only call
ExitProcess when all of its services are stopped.
Not true, all services must be stoped, started, paused, etc through the
SCM, and this has to be done preferably using an external program (the
reason is obvious right?), samples are the services control panel applet,

Well, it's not obvious to me, why couldn't a service decide to stop
running by itself?

At any rate I think the point is clear: a .NET service cannot easily stop
itself. We can agree to disagree about wether a C++ ATL service could. :)

Greetings,
Wessel
Nov 17 '05 #15

P: n/a
>> When it exits, it calls SetServiceStatus(..,SERVICE_STOPPED),
and then exits like a normal program with ExitProcess().
Not true, the SetServiceStatus is called when OnStop returns, calling
ExitProcess from within a service would be disastrous for processes
hosting
multiple services, you don't want to stop all your services hosted in the
same process don't you :-).

Every stopping service calls ExitProcess. The other option is the SCM
calling TerminateProcess(), and the SCM doesn't do that, obviously. A
third option would be to generate a Win32 Structured Exception (f.e.
segfault) to leave the process.

If there are multiple services in a process, the process would only call
ExitProcess when all of its services are stopped.
Not true, all services must be stoped, started, paused, etc through the
SCM, and this has to be done preferably using an external program (the
reason is obvious right?), samples are the services control panel applet,

Well, it's not obvious to me, why couldn't a service decide to stop
running by itself?

At any rate I think the point is clear: a .NET service cannot easily stop
itself. We can agree to disagree about wether a C++ ATL service could. :)

Greetings,
Wessel
Nov 17 '05 #16

P: n/a

"Wessel Troost" <no*****@like.the.sun> wrote in message
news:op.sua2dyqcf3yrl7@asbel...
When it exits, it calls SetServiceStatus(..,SERVICE_STOPPED),
and then exits like a normal program with ExitProcess().


Not true, the SetServiceStatus is called when OnStop returns, calling
ExitProcess from within a service would be disastrous for processes
hosting
multiple services, you don't want to stop all your services hosted in the
same process don't you :-).

Every stopping service calls ExitProcess. The other option is the SCM
calling TerminateProcess(), and the SCM doesn't do that, obviously. A
third option would be to generate a Win32 Structured Exception (f.e.
segfault) to leave the process.

If there are multiple services in a process, the process would only call
ExitProcess when all of its services are stopped.
Not true, all services must be stoped, started, paused, etc through the
SCM, and this has to be done preferably using an external program (the
reason is obvious right?), samples are the services control panel applet,

Well, it's not obvious to me, why couldn't a service decide to stop
running by itself?

At any rate I think the point is clear: a .NET service cannot easily stop
itself. We can agree to disagree about wether a C++ ATL service could. :)

Greetings,
Wessel


Sorry but I have to disagree.
First, <why couldn't a service decide to stop running by itself?>

When the SCM registers a service it creates a default security descriptor
for the Service Object, Local authenticated users like NETWORK SERVICE and
LOCAL SERVICE aren't granted SERVICE_START and SERVICE_STOP access rights.
That means if your service runs under one of these accounts (preferred and
strongly advisable), they aren't allowed to stop themselves or start/stop
any other service in the system (was the OP's issue right?). Services that
run as SYSTEM are granted SERVICE_STOP and SERVICE_START access rights
(amongst some other), local administrators and power users are granted all
access (SERVICE_ALL_ACCESS).
Note that above assumes you didn't modify the DACL for the service object
(something only administrator can do).

Or in short Service applications must conform to the interface rules of the
SCM, and this can only be guaranteed if both controller and service are
separate applications.

Second, <Every stopping service calls ExitProcess>.
Which is obviously not true, but ok, you relaxed this a bit:
< If there are multiple services in a process, the process would only call
ExitProcess when all of its services are stopped.>

But again, this is not how things works.
The ServiceControlDispatcher is started when the Service is started (by the
SCM SERVICE_START command), and it runs on a separate thread that doesn't
return until there is an error (like a rude kill) or all services in the
process have terminated accurately following the SCM interface SERVICE_STOP
protocol (see later). When all services in the process have terminated, the
SCM sends a control request to the dispatcher thread asking it to exit. When
the dispatcher thread terminates (that is when StartServiceCtrlDispatcher
returns) the process returns to the Run method class Dispose() on all
Service classes and finally exits Main() and the CLR handles the remaining
of the process shutdown. You see no ExitProcess called ever.
Ok, lets assume you want to call ExitProcess, but let's start with a
warning, never terminate a managed process using Win32 ExitProcess API, you
have to call Environment.Exit() so that the CLR can initiate an orderly
shutdown.
Now you can definitely call this method whenever you like in a service, but
you shouldn't, for the obvious reason that:

- You might disturb the SCM!
- you might have other services running in the process AND,
- your service might have dependent services running and these must be
stopped before your service stops.

The latter is taken care of by the ServiceController.Stop() [assumed you
call this from within your service, which you shouldn't do], but he! here
you have the same issue as explained above, the ServiceControler.Stop()
cannot stop dependencies from within the service unless it runs as
Administrator or localsystem.
The second one should be taken care of by you, that means that each service
needs to keep track of all services in the same process and only call
Environment.Exit() when all are stopped, not impossible to do but useless.
Why? well again the SCM didn't ask to stop, so you are not following the
interface rules imposed by the SCM, you probably didn't stop all running
threads, that might confuse the SCM and might result in a state where the
service cannot be 'stopped' or 'restarted'. If you follow the rules of the
SCM, and use the STOP protocol sequence (SERVICE_CONTROL_STOP/
SERVICE_STOPPED) the process will exit in an orderly fashion.
If the SERVICE_CONTROL_STOP request is not honored by a SERVICE_STOPPED, the
SCM will wait "WaitToKillServiceTimeout" registry value before terminating
the process.

Willy.




Nov 17 '05 #17

P: n/a

"Wessel Troost" <no*****@like.the.sun> wrote in message
news:op.sua2dyqcf3yrl7@asbel...
When it exits, it calls SetServiceStatus(..,SERVICE_STOPPED),
and then exits like a normal program with ExitProcess().


Not true, the SetServiceStatus is called when OnStop returns, calling
ExitProcess from within a service would be disastrous for processes
hosting
multiple services, you don't want to stop all your services hosted in the
same process don't you :-).

Every stopping service calls ExitProcess. The other option is the SCM
calling TerminateProcess(), and the SCM doesn't do that, obviously. A
third option would be to generate a Win32 Structured Exception (f.e.
segfault) to leave the process.

If there are multiple services in a process, the process would only call
ExitProcess when all of its services are stopped.
Not true, all services must be stoped, started, paused, etc through the
SCM, and this has to be done preferably using an external program (the
reason is obvious right?), samples are the services control panel applet,

Well, it's not obvious to me, why couldn't a service decide to stop
running by itself?

At any rate I think the point is clear: a .NET service cannot easily stop
itself. We can agree to disagree about wether a C++ ATL service could. :)

Greetings,
Wessel


Sorry but I have to disagree.
First, <why couldn't a service decide to stop running by itself?>

When the SCM registers a service it creates a default security descriptor
for the Service Object, Local authenticated users like NETWORK SERVICE and
LOCAL SERVICE aren't granted SERVICE_START and SERVICE_STOP access rights.
That means if your service runs under one of these accounts (preferred and
strongly advisable), they aren't allowed to stop themselves or start/stop
any other service in the system (was the OP's issue right?). Services that
run as SYSTEM are granted SERVICE_STOP and SERVICE_START access rights
(amongst some other), local administrators and power users are granted all
access (SERVICE_ALL_ACCESS).
Note that above assumes you didn't modify the DACL for the service object
(something only administrator can do).

Or in short Service applications must conform to the interface rules of the
SCM, and this can only be guaranteed if both controller and service are
separate applications.

Second, <Every stopping service calls ExitProcess>.
Which is obviously not true, but ok, you relaxed this a bit:
< If there are multiple services in a process, the process would only call
ExitProcess when all of its services are stopped.>

But again, this is not how things works.
The ServiceControlDispatcher is started when the Service is started (by the
SCM SERVICE_START command), and it runs on a separate thread that doesn't
return until there is an error (like a rude kill) or all services in the
process have terminated accurately following the SCM interface SERVICE_STOP
protocol (see later). When all services in the process have terminated, the
SCM sends a control request to the dispatcher thread asking it to exit. When
the dispatcher thread terminates (that is when StartServiceCtrlDispatcher
returns) the process returns to the Run method class Dispose() on all
Service classes and finally exits Main() and the CLR handles the remaining
of the process shutdown. You see no ExitProcess called ever.
Ok, lets assume you want to call ExitProcess, but let's start with a
warning, never terminate a managed process using Win32 ExitProcess API, you
have to call Environment.Exit() so that the CLR can initiate an orderly
shutdown.
Now you can definitely call this method whenever you like in a service, but
you shouldn't, for the obvious reason that:

- You might disturb the SCM!
- you might have other services running in the process AND,
- your service might have dependent services running and these must be
stopped before your service stops.

The latter is taken care of by the ServiceController.Stop() [assumed you
call this from within your service, which you shouldn't do], but he! here
you have the same issue as explained above, the ServiceControler.Stop()
cannot stop dependencies from within the service unless it runs as
Administrator or localsystem.
The second one should be taken care of by you, that means that each service
needs to keep track of all services in the same process and only call
Environment.Exit() when all are stopped, not impossible to do but useless.
Why? well again the SCM didn't ask to stop, so you are not following the
interface rules imposed by the SCM, you probably didn't stop all running
threads, that might confuse the SCM and might result in a state where the
service cannot be 'stopped' or 'restarted'. If you follow the rules of the
SCM, and use the STOP protocol sequence (SERVICE_CONTROL_STOP/
SERVICE_STOPPED) the process will exit in an orderly fashion.
If the SERVICE_CONTROL_STOP request is not honored by a SERVICE_STOPPED, the
SCM will wait "WaitToKillServiceTimeout" registry value before terminating
the process.

Willy.




Nov 17 '05 #18

P: n/a
> Note that above assumes you didn't modify the DACL for the service object
(something only administrator can do).
The service doesn't need SERVICE_START or SERVICE_STOP privileges to stop
itself. It can just call SetServiceStatus(), which is allowed regardless
of access privileges. The service can call this only to report its own
status, something which every service must do.
Or in short Service applications must conform to the interface rules of
the
SCM, and this can only be guaranteed if both controller and service are
separate applications.
Earlier we agreed (and the OP said) that his service could stop itself, if
it ran as local system?

There are many services that require local system privileges. Actually,
one of the main reasons for writing a service used to be increased
privileges.
of the process shutdown. You see no ExitProcess called ever.
Kind of a technicality really, but how do you think a userspace process
signals to the OS that it wants to stop?

When the Main() thread exits, the CLR will call ExitProcess().
- You might disturb the SCM!
The SCM can handle crashing services. In fact, I've killed tons of
services during development using TerminateProcess(), which is arguably
worse than ExitProcess(). The SCM never became disturbed.
- you might have other services running in the process AND,
- your service might have dependent services running and these must be
stopped before your service stops.
I agree that a service should exit nicely in these circumstances.
If the SERVICE_CONTROL_STOP request is not honored by a SERVICE_STOPPED,
the
SCM will wait "WaitToKillServiceTimeout" registry value before
terminating
the process.

My point was that the service can send a SERVICE_STOPPED without having
received a SERVICE_CONTROL_STOP. The service process can exit afterwards
(or not, if it has other things to do) and the SCM will know it has
stopped.

Greetings,
Wessel
Nov 17 '05 #19

P: n/a
> Note that above assumes you didn't modify the DACL for the service object
(something only administrator can do).
The service doesn't need SERVICE_START or SERVICE_STOP privileges to stop
itself. It can just call SetServiceStatus(), which is allowed regardless
of access privileges. The service can call this only to report its own
status, something which every service must do.
Or in short Service applications must conform to the interface rules of
the
SCM, and this can only be guaranteed if both controller and service are
separate applications.
Earlier we agreed (and the OP said) that his service could stop itself, if
it ran as local system?

There are many services that require local system privileges. Actually,
one of the main reasons for writing a service used to be increased
privileges.
of the process shutdown. You see no ExitProcess called ever.
Kind of a technicality really, but how do you think a userspace process
signals to the OS that it wants to stop?

When the Main() thread exits, the CLR will call ExitProcess().
- You might disturb the SCM!
The SCM can handle crashing services. In fact, I've killed tons of
services during development using TerminateProcess(), which is arguably
worse than ExitProcess(). The SCM never became disturbed.
- you might have other services running in the process AND,
- your service might have dependent services running and these must be
stopped before your service stops.
I agree that a service should exit nicely in these circumstances.
If the SERVICE_CONTROL_STOP request is not honored by a SERVICE_STOPPED,
the
SCM will wait "WaitToKillServiceTimeout" registry value before
terminating
the process.

My point was that the service can send a SERVICE_STOPPED without having
received a SERVICE_CONTROL_STOP. The service process can exit afterwards
(or not, if it has other things to do) and the SCM will know it has
stopped.

Greetings,
Wessel
Nov 17 '05 #20

P: n/a

"Wessel Troost" <no*****@like.the.sun> wrote in message
news:op.suc2l7kpf3yrl7@asbel...
Note that above assumes you didn't modify the DACL for the service object
(something only administrator can do).
The service doesn't need SERVICE_START or SERVICE_STOP privileges to stop
itself. It can just call SetServiceStatus(), which is allowed regardless
of access privileges. The service can call this only to report its own
status, something which every service must do.


Ok, I see your point, you aren't discussing services based on the FCL. The
framework (v1.x) lacks this level of control, that is you - can't call
SetServiceStatus at all, because they implemented the ServiceBase class to
follow (somewhat too strictly) the SCM interface protocol. That imposes a
problem when you need to abruptly shutdown a service without being requested
y the SCM.
Now, this is something that is taken care of in v2.0 through a method
ServiceBase.Stop(), which calls OnStop() followed by a call to
SetServiceStatus() with the SERVICE_STOPPED status set, followed by the
"Service stopped succesfuly" message written to the eventlog. When the
service is hosted, the AppDomain is unloaded before Stop() returns, then
it's up to the host to ExitProcess or do something else. If the service
isn't hosted, and there are no other active Services in the process, the
process exits through the normal CLR shutdown procedure, else the process
keeps running in the ServiceControlDispatcher.

Another change makes is the possible to extend the start and stop period, by
allowing to hint the SCM (START_PENDING etc...) when there are pending
requests.
Or in short Service applications must conform to the interface rules of
the
SCM, and this can only be guaranteed if both controller and service are
separate applications.

Earlier we agreed (and the OP said) that his service could stop itself, if
it ran as local system?


Yes, but not as local service or network service, which are the prefered
accounts.
There are many services that require local system privileges. Actually,
one of the main reasons for writing a service used to be increased
privileges.


I have to disagree, services should run according the principle of least
privilege, just like any other application in the system at least if you
care about security.
Too many services are running with system privileges, something that MSFT
also recognizes, and something they'll change in Longhorn (or Windows
VISTA).
of the process shutdown. You see no ExitProcess called ever.

Kind of a technicality really, but how do you think a userspace process
signals to the OS that it wants to stop?

When the Main() thread exits, the CLR will call ExitProcess().


That's what I meant with :
<and the CLR handles the remaining of the process shutdown.>
I know the CLR calls ExitProcess (it might even call TerminateProcess), what
I mean't was that user code (your code and the FCL) should never call
ExitProcess, and as the FCL never call's it, you won't see ExitProcess ever
called.

- You might disturb the SCM!


The SCM can handle crashing services. In fact, I've killed tons of
services during development using TerminateProcess(), which is arguably
worse than ExitProcess(). The SCM never became disturbed.

During development, right. But, ever killed services on a production server
running MS cluster server with potentially 5000++ users logged on?
The SCM doesn't guarantee to handle crashing services, it's not designed to
handle it, you might have done it several times without a problem, but that
doesn't mean it's common practice, all depends on the type of service, it
might fail and disturb the SCM. In short "killing" services is a bad
practice, just run "net stop servicename" to stop them, if this fails you
have a bug in your code which must be solved before you can call this
program a 'Service'.

- you might have other services running in the process AND,
- your service might have dependent services running and these must be
stopped before your service stops.

I agree that a service should exit nicely in these circumstances.

Sure, and the CLR makes things even more constrained, there are a number of
OS services that should never be called from managed code (and IMO these
services shouldn't even been exposed to managed code at all), Thread.Abort
is just one of them, Thread.Resume and Thread.Interupt are even been removed
fom v2.0.

Nov 17 '05 #21

P: n/a
> Ok, I see your point, you aren't discussing services based on the FCL.
Yeah. At some point I wrote "We can agree to disagree about wether a
C++ ATL service could.", and you replied "Sorry but I have to disagree.",
so I went on talking non-FCL after that.
I have to disagree, services should run according the principle of least
privilege, just like any other application in the system at least if you
care about security.
Agreed, my point was that if you really need higher privileges, a service
used to be the way to do it.
I mean't was that user code (your code and the FCL) should never call
ExitProcess, and as the FCL never call's it, you won't see ExitProcess
ever called.
Yeah.
During development, right. But, ever killed services on a production
server running MS cluster server with potentially 5000++ users logged on?
Haha, not 5000++ no, but over 100, sure. If your alternative is a reboot,
killing a service is the lower-impact option.
have a bug in your code which must be solved before you can call this
program a 'Service'.
I hope you're not saying that a 'Service' has to be bug-free. Terms like
"bug free program", "first-time right development", "fixed requirements"
are the telltale signs of a newbie project leader :)

Certainly a C++ service can be expected to crash the hard way. One of the
nice things about .NET is that it's very stable in the crashing
department. I've never seen a pure .NET program segfault.
Sure, but not in managed world (see above) where you don't have that
kind of
flexibility you have when programming against the low level Win32 API's.
This is the price you pay for simplicity, you can (to) quicly build a
windows service using the framework (didn't you notice the recent
Windows Service boom), but I seriously doubt this is a good thing.

Hmm, what's bad about simple services? They can start automaticcaly
after an "automatic update reboot". That's pretty nice for a background
program.

It also looks more professional. System operators prefer Services to a
simple Forms/Console application that does exactly the same thing.

Greetings,
Wessel
Nov 17 '05 #22

P: n/a
Inline
"Wessel Troost" <no*****@like.the.sun> wrote in message
news:op.sue1gnpwf3yrl7@asbel...
Ok, I see your point, you aren't discussing services based on the FCL. Yeah. At some point I wrote "We can agree to disagree about wether a C++
ATL service could.", and you replied "Sorry but I have to disagree.", so
I went on talking non-FCL after that.
I have to disagree, services should run according the principle of least
privilege, just like any other application in the system at least if you
care about security.


Agreed, my point was that if you really need higher privileges, a service
used to be the way to do it.

That doesn't mean it should run as SYSTEM, create a local service account
and grant the privileges he needs and enable the privilege in code, but
please don't put your service in the TCB, at least not on XP or higher. I
know W2K needs this to call LogonUser, but higher OS'ses don't need this
privilege any longer. Note also that on W2K3 and XP SP2, you cannot call
CreateProcessWithLogonW when running as Localsystem.
I mean't was that user code (your code and the FCL) should never call
ExitProcess, and as the FCL never call's it, you won't see ExitProcess
ever called.

Yeah.
During development, right. But, ever killed services on a production
server running MS cluster server with potentially 5000++ users logged on?

Haha, not 5000++ no, but over 100, sure. If your alternative is a reboot,
killing a service is the lower-impact option.

What's the difference 100 or 5000, killing a service that might crash other
services, or in the case of cluster server might crash the cluster service,
is defenately worse than a reboot of a single node.
have a bug in your code which must be solved before you can call this
program a 'Service'.

I hope you're not saying that a 'Service' has to be bug-free. Terms like
"bug free program", "first-time right development", "fixed requirements"
are the telltale signs of a newbie project leader :)

No, I'm in this business for 35 years now, I know that software is bug-free
until the first bug shows up. I say that it's clearly a bug when you can't
stop a service. and it's the kind of bug you should correct before the bugs
in the 'service' code, unless they are closely related. I've seen to many
services that run correctly otherwise but had problems to stop or didn't do
the right thing when stopping (process that keep running when the service
was stopped). One of the popular answers I heard was "services are designed
to run" not to stop.
I agree that not all services can/should be bullet proof, but at least when
they fail they should fail in a correct way, or to put it differently - they
should be as failsafe as possible (asp.net is one example of a fails safe
hosted service).
Especially business critical services that run on large boxes or in a
cluster should be designed such that they are fully controlled from the
outside, that is from the cluster manager (note that you shouldn't even use
the Services applet in a cluster case). They should also be designed to
correctly report their status when asked for, and they should be prepared to
fail over when they don't reply on the status requests.

Certainly a C++ service can be expected to crash the hard way. One of the
nice things about .NET is that it's very stable in the crashing
department. I've never seen a pure .NET program segfault.

Define a pure .NET program, never used PInvoke to call into native code and
have your arguments defined or the calling convention incorrectly? Sure the
message wouldn't look like a segfault, but a silently dying thread or
"execution engine error" leaving no trace in your logfile and he! its' a
service, so no user message on the destop either. Note that this is another
major problem in .NET, too much PInvoke using the wrong calling convention,
or passing incorrect types. This kind of error doesn't show up at the first
call (thanks to the hacks in the CLR that try to correct the calling
convention mistakes in user code), but it shows up only after hours or days
maybe, not a pretty face when this happens to a service and certainly not
easy to debug.
Sure, but not in managed world (see above) where you don't have that
kind of
flexibility you have when programming against the low level Win32 API's.
This is the price you pay for simplicity, you can (to) quicly build a
windows service using the framework (didn't you notice the recent
Windows Service boom), but I seriously doubt this is a good thing.

Hmm, what's bad about simple services? They can start automaticcaly
after an "automatic update reboot". That's pretty nice for a background
program.

A lot of them shouldn't run as a service but as a scheduled task, and don't
forget that the number of services are restricted in Windows (OS version
dependent). That's why I called it a "service boom", in my daily consultancy
job for a large company it became one of the most irritating questions to
ask - how many services are you running by now. The answers go leke; huh..
don't know, it doesn't matter it runs in the background at a lower
priortity; or the service is only actively running once a day for a couple
of minutes.
It also looks more professional. System operators prefer Services to a
simple Forms/Console application that does exactly the same thing.

Sure, and they want the service to have a UI too ;-). which is just another
problem source since the intro of .NET. (not .NET fault though).

Greetings,
Willy.
Nov 17 '05 #23

P: n/a
> No, I'm in this business for 35 years now, I know that software is

Cheers :)

And I agree with the rest of your post.

Greetings,
Wessel
Nov 17 '05 #24

This discussion thread is closed

Replies have been disabled for this discussion.