Window Service

  • Thread starter Thread starter BW
  • Start date Start date
B

BW

Hi all! I'm not sure where to post this so I'm giving these a try. If there
is a better (more appropriate) place to post please let me know.

I want to create a service (in C#). The service's purpose is to monitor a
given service, and when the service becomes disabled and/or stopped I want
to restart the service.

I have figured out how to restart a stopped service by using the
ServiceController.Start() method.

Obviously,this only works if the service is enabled. So, I must enabled the
service before I can restart it.

Does anyone know how to re-enable the a service that had been disabled?


TIA
BW

I do have a very good reason for doing this and it is not malicious in
nature.
 
You need set the StartType property using ServiceInstaller. I've never done
this, so you may need to uninstall and reinstall the service for this to
take.
 
BW said:
Hi all! I'm not sure where to post this so I'm giving these a try. If
there
is a better (more appropriate) place to post please let me know.

I want to create a service (in C#). The service's purpose is to monitor a
given service, and when the service becomes disabled and/or stopped I want
to restart the service.

I have figured out how to restart a stopped service by using the
ServiceController.Start() method.

Obviously,this only works if the service is enabled. So, I must enabled
the
service before I can restart it.

Does anyone know how to re-enable the a service that had been disabled?


TIA
BW

I do have a very good reason for doing this and it is not malicious in
nature.
And what if your watchdog service gets stopped/disabled?

Willy.
 
Good question, Willy!

The truth is, I really don't care.

Here's the situation: the powers that be have determined that there are
exploits in the debug service (MDM). So, periodically (twice per day
minimum) the active directory (don't know it that's the correct term here,
it's what they call it) goes out on the LAN and kills MDM and disables it.

This, of course, makes it next to impossible to debug. And the network
people refuse to single out the developer group.

So, when we are trying to debug and the and the service goes down, I have
written a batch file so devs can enable the service and restart it. and I'm
looking for a way to do this in code, so I can write a monitor service.

The thing that kills the debug service won't kill mine since they don't know
about it. they only kill "known" services.

I'm also not married to the idea of my app being a service. It could just as
easily be a windows app that sits in the background to do the monitoring.

-- BW
 
Hi,

I think that the easiest way to do it is updating the registry, in
System\\CurrentControlSet\\Services\\ServiceName there is a flag for this, I
do not remember the correct value but it's easy to see it.


cheers,
 
BW said:
Good question, Willy!

The truth is, I really don't care.

Here's the situation: the powers that be have determined that there are
exploits in the debug service (MDM). So, periodically (twice per day
minimum) the active directory (don't know it that's the correct term here,
it's what they call it) goes out on the LAN and kills MDM and disables it.

This, of course, makes it next to impossible to debug. And the network
people refuse to single out the developer group.

So, when we are trying to debug and the and the service goes down, I have
written a batch file so devs can enable the service and restart it. and
I'm
looking for a way to do this in code, so I can write a monitor service.

The thing that kills the debug service won't kill mine since they don't
know
about it. they only kill "known" services.

I'm also not married to the idea of my app being a service. It could just
as
easily be a windows app that sits in the background to do the monitoring.

-- BW


I see, well, I suggest you don't put to much effort in this yourself and
simply use Process.Start to run sc.exe, this utility can do anything that
can possibly be done with a service.
Another option is to use System.Management and WMI.
Herewith is a small console program to give you a head start. Start this
program from the console window , disable mdm followed by a stop mdm, you'll
see that the service restarts and the is enabled again.

using System;
using System.ComponentModel;
using System.Runtime.InteropServices;
using System.Management;
class WMIEvent {
public static void Main() {
WMIEvent we = new WMIEvent();
ManagementEventWatcher w= null;
WqlEventQuery q;
ManagementOperationObserver observer = new ManagementOperationObserver();

// Bind to local machine
ManagementScope scope = new ManagementScope("root\\CIMV2");
scope.Options.EnablePrivileges = true; //sets required privilege
try {
q = new WqlEventQuery();
q.EventClassName = "__InstanceOperationEvent";
q.Condition = @"TargetInstance ISA 'Win32_Service' and
TargetInstance.Name='mdm'";
q.WithinInterval = new TimeSpan(0,0,10); // poll interval 10 secs.
w = new ManagementEventWatcher(scope, q);
w.EventArrived += new EventArrivedEventHandler(we.ServiceEventArrived);
w.Start();
System.Threading.Thread.Sleep(-1); // suspend thread

}
catch(Exception e) {
Console.WriteLine(e);
}
finally
{
w.Stop();
}

}

public void ServiceEventArrived(object sender, EventArrivedEventArgs e) {
ManagementBaseObject mbo =
(ManagementBaseObject)e.NewEvent["TargetInstance"];
if((bool)mbo["Started"] == false)
{
Console.WriteLine("Service:{0} stopped", mbo["DisplayName"]);
RestartService(mbo["Name"].ToString());
}
}

public void RestartService(string ServiceName)
{
ManagementPath myPath = new ManagementPath();
ManagementBaseObject outParams = null;
myPath.Server = System.Environment.MachineName;
myPath.NamespacePath = @"root\CIMV2";
myPath.RelativePath = "Win32_Service.Name='" + ServiceName + "'";
using (ManagementObject service = new ManagementObject(myPath))
{
// Set startmode to Automatic (auto start at boot )
ManagementBaseObject inputArgs =
service.GetMethodParameters("ChangeStartMode");
inputArgs["startmode"] = "Automatic";
outParams = service.InvokeMethod("ChangeStartMode", inputArgs, null);
// return check ignored for brevity
uint ret = (uint)(outParams.Properties["ReturnValue"].Value);
if(ret == 0)
Console.WriteLine("Service startmode changed");
else Console.WriteLine("Startmode Failed with error code: {0}", ret);
// Start service
outParams = service.InvokeMethod("StartService", null, null);
ret = (uint)(outParams.Properties["ReturnValue"].Value);
if(ret == 0)
Console.WriteLine("Service Restart Succeeded");
else Console.WriteLine("Failed with error code: {0}", ret);
}
}
}


Willy.
 
Yep, sc is what I'm currently using in the batch file I wrote.

I was just looking to find a more elegant way rather than shelling out to do
it.

I'll take a look at the WMI stuff this weekend.

Thanks a lot, Willy!


Regards,
BW

Willy Denoyette said:
BW said:
Good question, Willy!

The truth is, I really don't care.

Here's the situation: the powers that be have determined that there are
exploits in the debug service (MDM). So, periodically (twice per day
minimum) the active directory (don't know it that's the correct term here,
it's what they call it) goes out on the LAN and kills MDM and disables it.

This, of course, makes it next to impossible to debug. And the network
people refuse to single out the developer group.

So, when we are trying to debug and the and the service goes down, I have
written a batch file so devs can enable the service and restart it. and
I'm
looking for a way to do this in code, so I can write a monitor service.

The thing that kills the debug service won't kill mine since they don't
know
about it. they only kill "known" services.

I'm also not married to the idea of my app being a service. It could just
as
easily be a windows app that sits in the background to do the monitoring.

-- BW


I see, well, I suggest you don't put to much effort in this yourself and
simply use Process.Start to run sc.exe, this utility can do anything that
can possibly be done with a service.
Another option is to use System.Management and WMI.
Herewith is a small console program to give you a head start. Start this
program from the console window , disable mdm followed by a stop mdm, you'll
see that the service restarts and the is enabled again.

using System;
using System.ComponentModel;
using System.Runtime.InteropServices;
using System.Management;
class WMIEvent {
public static void Main() {
WMIEvent we = new WMIEvent();
ManagementEventWatcher w= null;
WqlEventQuery q;
ManagementOperationObserver observer = new ManagementOperationObserver();

// Bind to local machine
ManagementScope scope = new ManagementScope("root\\CIMV2");
scope.Options.EnablePrivileges = true; //sets required privilege
try {
q = new WqlEventQuery();
q.EventClassName = "__InstanceOperationEvent";
q.Condition = @"TargetInstance ISA 'Win32_Service' and
TargetInstance.Name='mdm'";
q.WithinInterval = new TimeSpan(0,0,10); // poll interval 10 secs.
w = new ManagementEventWatcher(scope, q);
w.EventArrived += new EventArrivedEventHandler(we.ServiceEventArrived);
w.Start();
System.Threading.Thread.Sleep(-1); // suspend thread

}
catch(Exception e) {
Console.WriteLine(e);
}
finally
{
w.Stop();
}

}

public void ServiceEventArrived(object sender, EventArrivedEventArgs e) {
ManagementBaseObject mbo =
(ManagementBaseObject)e.NewEvent["TargetInstance"];
if((bool)mbo["Started"] == false)
{
Console.WriteLine("Service:{0} stopped", mbo["DisplayName"]);
RestartService(mbo["Name"].ToString());
}
}

public void RestartService(string ServiceName)
{
ManagementPath myPath = new ManagementPath();
ManagementBaseObject outParams = null;
myPath.Server = System.Environment.MachineName;
myPath.NamespacePath = @"root\CIMV2";
myPath.RelativePath = "Win32_Service.Name='" + ServiceName + "'";
using (ManagementObject service = new ManagementObject(myPath))
{
// Set startmode to Automatic (auto start at boot )
ManagementBaseObject inputArgs =
service.GetMethodParameters("ChangeStartMode");
inputArgs["startmode"] = "Automatic";
outParams = service.InvokeMethod("ChangeStartMode", inputArgs, null);
// return check ignored for brevity
uint ret = (uint)(outParams.Properties["ReturnValue"].Value);
if(ret == 0)
Console.WriteLine("Service startmode changed");
else Console.WriteLine("Startmode Failed with error code: {0}", ret);
// Start service
outParams = service.InvokeMethod("StartService", null, null);
ret = (uint)(outParams.Properties["ReturnValue"].Value);
if(ret == 0)
Console.WriteLine("Service Restart Succeeded");
else Console.WriteLine("Failed with error code: {0}", ret);
}
}
}


Willy.
 
changing this value directly will only confuse the SCM. The SCM uses the
registry to store state across reboots, but does not necessarily update its
state based on runtime registry changes. Use the SCM APIs, like
ChangeServiceConfig() (don't know the C# equivalent).
 
Back
Top