Stop a Windows Service Programattically

D

David Garner

I have a windows service. In the OnStart() method I
validate the startup parameters. If any of the parameters
are invalid I write an entry to the EventLog. I also want
to stop the service from running. I can't figure out how
to do this.

I have used...

if( invalid )
{
EventLog.WriteEntry( this.ServiceName,
"Service will be stopped" );
System.ServiceProcess.ServiceController svctlr =
new ServiceController( this.ServiceName );
svctlr.Stop();
svctlr.Close();
}

The event log has the entry, but the service continues to
run.

What am I missing here?

However, when the boolean value invalid is true,
 
D

David Garner

Uhm. Nope.

For one, this is C# code. There is no "end" keyword.
Second this is a Windows Service, (not a regular
application) or I'd just use Application.End();

The ServiceBase and the ServiceController classes do not
have an end.

Is there some way I can send a shutdown event?

Anyone?

I'm almost content to the let the users have to remember
to go to the EventLog to see if the service had any
problems starting.
 
W

Willy Denoyette [MVP]

David Garner wrote:
|| I have a windows service. In the OnStart() method I
|| validate the startup parameters. If any of the parameters
|| are invalid I write an entry to the EventLog. I also want
|| to stop the service from running. I can't figure out how
|| to do this.
||
|| I have used...
||
|| if( invalid )
|| {
|| EventLog.WriteEntry( this.ServiceName,
|| "Service will be stopped" );
|| System.ServiceProcess.ServiceController svctlr =
|| new ServiceController( this.ServiceName );
|| svctlr.Stop();
|| svctlr.Close();
|| }
||
|| The event log has the entry, but the service continues to
|| run.
||
|| What am I missing here?
||
|| However, when the boolean value invalid is true,

Two possibilities:
1. Throw an exception, the SCM will stop the service
2. Sleep for at least 30 seconds, the SCM will pull down the service.

Willy.
 
D

David Garner

Yup, that will work. But, I was hoping for a more elegant
solution.

I've decided to go with:

Environment.Exit( Process.ExitCode );

This is only slightly more elegant than throwing an
unnecessary exception which provides a frightening (at
least to the end user) messageBox or sleeping for 30
seconds (some of my users will try rebooting the computer
if something doesn't move for 30 seconds).

The Exit() method produces a pretty bad message box as
well.

Thanks Willy
 
J

Jerry Ham

What I was trying to get at is that you can't send a shutdown event to
yourself when you are still processing your startup (I think you saw this
when you managed to have it hang). You really need to just end your program.
Sorry, I haven't played with this enough (and sure don't have the time to),
but if application.exit is not in scope due to ServiceBase, you may need to
use API code or something to do it.

Now, you may be able to set a flag in your onStart that allows some other
thread (I don't know your app; maybe you have worker threads, maybe you
don't).

I actually would have thought that the onStart would be able to return
"false" if initialization had a problem, but I see it can't return a value.
It does look like an oversight.
 
D

David Garner

I agree it is an oversight.

What I'm using is Environment.Exit( Environment.ExitCode );

Other choices would be to force an error by throwing an
exception or by timing out the OnStart() method by
sleeping for 30 seconds.

Not very elegant huh?

Thanks for trying.

I also thought about spawning another thread (which, by
the way is the recommended practice when initializing a
service could take longer than the 30 second time limit)
and then using that thread to send the
ServiceController.Stop() method. But for what I'm doing
that would be a tremendous amount of overkill.

Like I always say, to find out how something works, you
have to find out how it doesn't work as well.

Thanks a lot
David
 
S

Scott Numbers

Hello,

I am by far not a C-Sharp guru but I have found a simple way to
start/stop a service. I start a new thread to do the Service process
in the OnStart() function and on OnStop() I try to make the Run() loop
exit gracefully. If it is still running after a specified time, I kill
the Thread with Thread.Abort() You may find a little more graceful way
than this, but so far, I haven't had a problem. I would guess you
have to start a new thread or procecss in the OnStart() since you
can't put your main process in the OnStart() Entrypoint. You have to
return from the OnStart function relatively quickly or the Service
Control Manager will complain. I cannot say whether Thread.Abort()
will do all of the necessary freeing/disposing of resources that you
might like. You may need to use private member variables to keep track
of Forms (not recommended in services) or other resources that you
want to make sure are disposed of properly.

Anyway, here is the sample code... A sample is worth a million words
when you are new to a language--And boy do I appreciate all of the
great examples found here in the Google Forums. I hope this is of some
help to you. If not, good luck in your search for your answers.

Scott Numbers
numbers @ adelphia.net


using System;
using System.Collections;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.ServiceProcess;
using System.Threading;

namespace WindowsService1
{
public class Service1 : System.ServiceProcess.ServiceBase
{
private System.ComponentModel.Container components = null;
private System.Threading.Thread ServiceThread =
(System.Threading.Thread) null;
private bool mRunning = false;
public Service1()
{
InitializeComponent();
}

static void Main()
{
System.ServiceProcess.ServiceBase[] ServicesToRun;
ServicesToRun = new System.ServiceProcess.ServiceBase[]
{ new Service1() };
System.ServiceProcess.ServiceBase.Run(ServicesToRun);
}

private void Run()
{
// Do your service Loop/Listener/Whatever
// Possible loop
while (mRunning) {
Thread.Sleep(5000); // Sleep 5 seconds
if (xyz) {
DoSomething();
}
}
}

private void InitializeComponent()
{
components = new System.ComponentModel.Container();
this.ServiceName = "Service1";
}

protected override void Dispose( bool disposing )
{
if( disposing )
{
if (components != null)
{
components.Dispose();
}
}
base.Dispose( disposing );
}

protected override void OnStart(string[] args)
{
mRunning = true;
System.Threading.ThreadStart ts =
new System.Threading.ThreadStart(Run);
ServiceThread = new System.Threading.Thread(ts);
ServiceThread.Start();
}

protected override void OnStop()
{
mRunning = false;
// Time should be longer than Run() loop takes to execute.
Thread.Sleep(8000);
// If the thread hasn't exited on its own by now,
// Kill it.
if (ServiceThread.IsAlive) ServiceThread.Abort();
// I'm lost if I can't say "Set xyz = Nothing"
ServiceThread = (System.Threading.Thread) null;
}
}
}
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top