Luke Jones CV

    HOME        CODE TIPS        KILLING SERVICES PROGRAMATICALLY WITH C#

Now I'd like to add that I know very little about creating application's that run on Windows. That's not to say I'm not interested, it's just that websites take up most of my time but as of late I've been loosing my rag with my computer due to the time it takes to swap development platforms. See like many others I run both SQLServer Express and Apache on my computer. One for running .NET, the other for PHP.

The other day I was asked by a friend if I knew of how to kill processes and services programatically to enable a programme to be built that could shutdown these programmes which would be quicker then the time it takes to kill the services manually. I replied 'I know exactly what you mean!' and that not only did I know how, but we can also start the services back up again. The reply was 'cool!' and''Could you make a programme that swaps these services to enable or disable development platforms?' I said... 'probably'. Now I had been tinkering with this thought myself for some time and I really didn't have the time to make anything all to fancy And so I built for him a rough build of this software from which he could tweak it to his own liking. I'm going to present here the basic code for killing services and processes which will give you a head start in building your own programme for doing this.

Services and Processes

First of all and and keeping it brief, a Service is any software that is run under Windows in the background and is registered as a Windows service; you can find these in the following location: Control Panel > Administrative Tools > Services.

Services create Processes. You can view all your processes by hitting (Right Now!) ctrl + alt + delete and going to the processes tab. All software creates an active process, BUT not all processes are services. Some are just software you've got on your hard drive that run a programme in the background. Take for example Spybot - Search and Destroy's teatimer.exe programme that constantly monitors your registry keeping it safe from any malicious tampering and other nasty things out there on the net.

Killing Services

The primary use of this code is to kill multiple processes and multiple services at the click of a button. Multiple services means that we are going to need to create a List of services, and that probably a 'foreach' loop would be used to specify commands for each of the services added to the list. Therefore it's best to create some small wrapper objects for the services and processes. In your Windows Form Project in Visual Studio create a new class and call it for example, Objects.cs. Now lets create the objects.

1   public class ServiceObject
2   {
3      private string _machineName = ".";
4      public string MachineName
5      {
6         get { return _machineName; }
7      }
8
9      private string _name = "";
10     public string Name
11     {
12        get { return _name; }
13        set { _name = value; }
14     }
15
16     public ServiceObject(string name)
17     {
18        this.Name = name;
19     }
20  }
21
22  public class ProcessObject
23  {
24     private string _processName = "";
25     public string ProcessName
26     {
27        get { return _processName; }
28        set { _processName = value; }
29     }
30
31     private string _processAddress = "";
32     public string ProcessAddress
33     {
34        get { return _processAddress; }
35        set { _processAddress = value; }
36     }
37
38     public ProcessObject(string processName, string processAddress)
39;     {
40        this.ProcessName = processName;
41        this.ProcessAddress = processAddress;
42     }
43  }

So no big deal here all we're doing is creating a couple of Objects, a Service Object, and a Process Object and each having there own attributes. As I mentioned above, Processes and Services are different things. Services can create processes but not all processes are services. Therefore we have to use a different method in order to shut these down. I reccomend wrapping the above objects in a namespace of your choice (As a rule I reccomend namespacing all code you write).

If you haven't one already create a new form in your project and open it up in code view. Now we're going to create a few ServiceObjects and ProcessObjects. These objects are hard-coded because as of yet I've not had time to build it more elegantly so that it get's all of these values programatically - if it can even be done because as of yet I haven't tried this. If you know how I'd like to hear from you. So lets create a few objects;

1   public partial class MyForm : Form
2   {
3      // *** PROCESSES TO KILL *** //
4
5      public ProcessObject POTeaTimer = new ProcessObject("TeaTimer.exe", "C:\\Program Files\\Spybot - Search & Destroy\\");
6      public ProcessObject POBitTorrent = new ProcessObject("btdna.exe", "C:\\Program Files\\DNA\\");
7
8      // *** APACHE SERVICES TO KILL *** //
9
10     //Apache configuration objects
11     public ServiceObject SObjApache = new ServiceObject("Apache2.2");
12     public ServiceObject SObjMySql = new ServiceObject("mysql");
15
16     //Object List's
17     List ServiceList = new List();
18     List ProcessList = new List();

Again Nothing to complicated, all we've done is created some ProcessObjects and ServiceObjects and created two list's to contain them. The question is where do the values that we put inside the parameters come from?

The ProcessObject's parameters first takes the name of the executable, and then the address in your computers folder directory from where this executable can be found. If you attach the first parameter to the second you will have the entire folder address. So why don't we just do this? The reason for this is that if you press ctrl + alt + delete and check your processes tab, all the processes are defined by there executables name under the 'Image Name' and programtically we need also to find the process by its 'Image Name'. It is possible that you may have multiple instances of an Image Name running, for instance take svchost.exe which is usually a generic windows process, a normal system usually has 5 or 6 of these running at the same time. What does this mean? It means that you cant differentiate between one svchost.exe and the next. If you ask it to kill one svchost.exe, it will kill all svchost.exe's. Make sure that what ever process you want to kill can be specified and is unique. If your having trouble finding where the Executable is in your folder directory use SpyBot's StartUp manager, or TweakUI, or even Windows search.

The ServiceObject parameter is easier to locate then the processes. The parameter takes the Service Name of the Service. This is the name windows uses to locate the Service from Windows Services. Go to Start > Settings > Control Panel > Administrative Tools > Services. Locate the Service you wish to shut down and right-click > properties that service. The Service Name can be found at the top of the opened Properties Form under 'Service Name'. The Service Name is almost always unique.

Next step is in the 'Form_Load' handler, add all of the ServiceObject's and ProcessObject's to the Lists we built. e.g.

ProcessList.Add(POTeaTimer);
ProcessList.Add(POBitTorrent);
ServiceList.Add(SObjApache);
ServiceList.Add(SObjMySql);

Finally we get down to actually killing these services. Now the process is different for Services and Processes so here are the functions utilising the List's we've created.

Killing Services

1   foreach (ServiceObject service in ServiceList)
2   {
3      ServiceController SC = new ServiceController();
4      SC.MachineName = service.MachineName;
5      SC.ServiceName = service.Name;
6      if (SC.Status.ToString().ToLower() == "running")
7         SC.Stop();
8   }

Killing Processes

1   ManagementPath mp = new ManagementPath(@"\\ComputerName" + @"\ROOT\CIMV2:Win32_Process");
2   foreach (ProcessObject PO in ProcessList)
3   {
4      ManagementObjectCollection mc = new ManagementClass(mp).GetInstances();
5      foreach (ManagementObject mo in mc)
6      {
7         Debug.WriteLine(mo.Properties["Name"].Value.ToString());
8         if (mo.Properties["Name"].Value.ToString().ToUpper() == PO.ProcessName.ToUpper())
9         {
10           object[] methodArgs = { 0 };
11           mo.InvokeMethod("Terminate", methodArgs);
12        }
13     }
14  }

So quickly through these functions then; the method to kill service objects is simply identifying the service by its Service Name and if it identifies its Status as 'Running' then it shuts it down. The method to kill Processes however is a little more complicated in that the method creates a collection of Management Objects (Line 4) from the Management Path we declare in Line 1 (Here is a good time to tell you that where it states ComputerName you should put the name of your computer. If you've forgotten what this is then right-click on My Computer, go to Properties and select the 'Computer Name' tab. The name of your computer is under 'Full Computer Name'). The Method then validates each of the Process Objects in the Project List we've created, and attempts to find them in the Management Object Collection by there name (Line 8). If the names are the same, then it shuts them down by invoking the 'Terminate' method (line 12) but not before creating a dummy arguement object as the method (line 11) will not run without them.

These functions are probably best suited as Private Void function, so set up a couple of functions and name them as you like.

So that is how you kill multiple functions and processes in a single blow. Now setup your form with a button and when OnClick occurs activate the functions. So thats great and what have you, but how do we restart the functions? Very Simple.

Restarting services

It's simply a matter of validating for the Opposite status. Simply change line 6 of 'Killing Services' to if (SC.Status.ToString().ToLower() != "running") then SC.Start()

Restarting Processes

Much simpler then killing services it really is quite self-explanatory. It simply executes the executable located at the address created by concatinating both address and name strings of the ProcessObject we created earlier by using the Process.Start Method.

1   foreach (ProcessObject PO in ProcessList)
2   {
3      Process.Start(PO.ProcessAddress + PO.ProcessName);
4   };

So there you have it, how to terminate and restart both Windows Services and Processes. Once again if there are any problems or have questions to ask please feel free to contact me.