Finding out Windows service's running process name .NET 1.1
Asked Answered
E

6

10

We are using a badly written windows service, which will hang when we are trying to Stop it from code. So we need to find which process is related to that service and kill it. Any suggestions?

Erena answered 19/2, 2009 at 14:53 Comment(0)
S
5

WMI has this information: the Win32_Service class.

A WQL query like

SELECT ProcessId FROM Win32_Service WHERE Name='MyServiceName'

using System.Management should do the trick.

From a quick look see: taskllist.exe /svc and other tools from the command line.

Simulacrum answered 19/2, 2009 at 15:0 Comment(0)
U
15

You can use System.Management.MangementObjectSearcher to get the process ID of a service and System.Diagnostics.Process to get the corresponding Process instance and kill it.

The KillService() method in the following program shows how to do this:

using System;
using System.ComponentModel;
using System.Diagnostics;
using System.Management;

namespace KillProcessApp {
    class Program {
        static void Main(string[] args) {
            KillService("YourServiceName");
        }

        static void KillService(string serviceName) {
            string query = string.Format(
                "SELECT ProcessId FROM Win32_Service WHERE Name='{0}'", 
                serviceName);
            ManagementObjectSearcher searcher = 
                new ManagementObjectSearcher(query);
            foreach (ManagementObject obj in searcher.Get()) {
                uint processId = (uint) obj["ProcessId"];
                Process process = null;
                try
                {
                    process = Process.GetProcessById((int)processId);
                }
                catch (ArgumentException)
                {
                    // Thrown if the process specified by processId
                    // is no longer running.
                }
                try
                {
                    if (process != null) 
                    {
                        process.Kill();
                    }
                }
                catch (Win32Exception)
                {
                    // Thrown if process is already terminating,
                    // the process is a Win16 exe or the process
                    // could not be terminated.
                }
                catch (InvalidOperationException)
                {
                    // Thrown if the process has already terminated.
                }
            }
        }
    }
}
Ulland answered 19/2, 2009 at 16:26 Comment(2)
Good code thanks. However, I'd change "if (process != null)" to "if (process != null && process.Id > 0)". Windows won't let you kill process zero but it's better not to even try. Quicker to test for it than to raise and catch an Exception.Abash
I found I needed DisplayName as per @the berserker as I didn't have the short Windows name. I also found that retrieving the process id could be reduced from ~1s to ~25ms using this solution: #1574519Pretorius
S
5

WMI has this information: the Win32_Service class.

A WQL query like

SELECT ProcessId FROM Win32_Service WHERE Name='MyServiceName'

using System.Management should do the trick.

From a quick look see: taskllist.exe /svc and other tools from the command line.

Simulacrum answered 19/2, 2009 at 15:0 Comment(0)
D
4

You can use

tasklist /svc /fi "SERVICES eq YourServiceName"

To find the process name and id, and also if the same process hosts other services.

Danille answered 19/2, 2009 at 15:6 Comment(0)
E
3

To answer exactly to my question - how to find Process related to some service:

ManagementObjectSearcher searcher = new ManagementObjectSearcher
  ("SELECT * FROM Win32_Service WHERE DisplayName = '" + serviceName + "'");

foreach( ManagementObject result in searcher.Get() )
{
  if (result["DisplayName"].ToString().ToLower().Equals(serviceName.ToLower()))
  {
    int iPID = Convert.ToInt32( result["ProcessId"] );
    KillProcessByID(iPID, 1000); //some method that will kill Process for given PID and timeout. this should be trivial
  }
}

}

Erena answered 20/2, 2009 at 11:47 Comment(1)
DisplayName worked better than Name for me, but I found the process id retrieval slow (if that's important to you) ~1s, whereas for this solution about ~25ms: #1574519Pretorius
K
0

Microsoft/SysInternals has a command-line tool called PsKill that allows you to kill a process by name. This tool also allows you to kill processes on other servers. Windows SysInternals

Usage: pskill [-t] [\computer [-u username [-p password]]] <process ID | name>
   -t  Kill the process and its descendants.
   -u  Specifies optional user name for login to remote computer.
   -p  Specifies optional password for user name. If you omit this you will be prompted to enter a hidden password.

Kiyohara answered 19/2, 2009 at 16:52 Comment(0)
S
0

I guess it's a two step process - if it's always the same service, you can easily find the process name using methods suggested in other answers.

I then have the following code in a class on a .NET 1.1 web server:

Process[] runningProcs = 
          Process.GetProcessesByName("ProcessName");

foreach (Process runningProc in runningProcs)
{
    // NOTE: Kill only works for local processes
    runningProc.Kill();
}

The Kill method can throw a few exceptions that you should consider catching - especially the Win32Exception, that is thrown if the process cannot be killed.

Note that the WaitForExit method and HasExited property also exist in the 1.1 world, but aren't mentioned on the documentation page for Kill in 1.1.

Sinus answered 19/2, 2009 at 16:52 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.