I was recently asked by a friend how to retrieve the name of a running windows service from the Service Control Manager (SCM) database. He wanted to do this from .NET, using the process id of the service. I started to think of different ways that this could be accomplished and came up with a couple, utilizing WMI.NET. Both approaches are similar, with a slight variation in the second.
First Solution
This function gets the service’s name by retrieving all services registered with the SCM, and comparing their process ids to the one supplied.
public static string GetServiceNameByProcessId(uint processId) { string serviceName = String.Empty; ManagementClass mc = new ManagementClass("Win32_Service"); foreach (ManagementObject service in mc.GetInstances()) { if ((uint)service["ProcessId"] == processId) { serviceName = (string)service["Name"]; break; } } return serviceName; }
Second Solution
This function uses WQL to query for the specific service instance, using the process id in the WHERE clause. This avoids having to iterate over all the services within the SCM.
public static string GetServiceNameByProcessId(uint processId) { string serviceName = String.Empty; SelectQuery query = new SelectQuery("Win32_Service", String.Format("ProcessId={0}", processId)); ManagementObjectSearcher searcher = new ManagementObjectSearcher(query); foreach (ManagementObject service in searcher.Get()) { if ((uint)service["ProcessId"] == processId) { serviceName = (string)service["Name"]; break; } } return serviceName; }
So, there you have it. These are the approaches that I came up with. In the future, I may present another that uses the Windows API, in particular the EnumServicesStatusEx function, to accomplish the same task. Can anyone think of other approaches or suggest changes to the ones I’ve presented?