0

I'm not writing a process viewer, but need somewhat the same concept. I can do

List<Process> allProcesses = Process.GetProcesses().ToList();

Question: How can I tell which process is a normal process and which is a windows service? I've dug through the properties of Process and not finding a flag of any sort.

Chizl
  • 2,004
  • 17
  • 32
  • 1
    [ServiceController](https://learn.microsoft.com/en-us/dotnet/api/system.serviceprocess.servicecontroller) class -- [Win32_Service](https://learn.microsoft.com/en-us/windows/win32/cimwin32prov/win32-service) – Jimi Mar 29 '22 at 01:34
  • You have to look at the parent process. Desktop apps are launched by Explorer and Services by the service control manager. – David Browne - Microsoft Mar 29 '22 at 01:36
  • @DavidBrowne-Microsoft, I'm not looking if I'm the service or I'm running as a service.. Read the question again. I'm asking how I can tell if something else is running as a service or not. – Chizl Mar 29 '22 at 01:45
  • 1
    What I mean is, if you look at the `Win32_Service` class, the `ProcessId` property can link to the `ProcessId` of a Process object. The ServiceController class is useful because it lists the Dependencies. – Jimi Mar 29 '22 at 02:56
  • Right. The only way is to look at its parent process. – David Browne - Microsoft Mar 29 '22 at 03:16
  • Looking at ServiceController, but have concerns and ServiceController doesn't hold ProcessID.. I found ManagementObjectSearcher might work better. Jimi, yours gave me direction with Win32_Service, thanks. – Chizl Mar 29 '22 at 16:34
  • @DavidBrowne-Microsoft Process() class doesn't have Parent. You would still have to go do PerfMon or ManagementObjectSearch to find the parent. I believe my solution is a bit more simple and less overhead. Thanks though. – Chizl Mar 29 '22 at 16:48

1 Answers1

0
private bool IsService(Process p, out string serviceName)
{
    bool retVal = false;
    serviceName = "";

    string query = $"SELECT Name FROM Win32_Service WHERE ProcessId={p.Id}";
    ManagementObjectSearcher searcher = new ManagementObjectSearcher(query);
    foreach (ManagementObject obj in searcher.Get())
    {
        serviceName = obj["Name"].ToString();
        retVal = true;
        break;
    }

    return retVal;
}
Chizl
  • 2,004
  • 17
  • 32
  • 1
    That works, for the main process hosting each service, but not for child processes it spawns. – David Browne - Microsoft Mar 29 '22 at 17:20
  • 1
    You may also use [OpenThread()](https://learn.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-openthread) (with `THREAD_QUERY_INFORMATION` as `DesiredAccess`) using the Process Threads collection, then call [GetProcessIdOfThread()](https://learn.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-getprocessidofthread) passing the previously returned handle (of course call `CloseHandle()` after). – Jimi Mar 29 '22 at 17:39
  • 1
    @DavidBrowne-Microsoft I ended up moving to Win32_Service to pull Services and Win32_Process for all processes including Services.. My List then holds all processes with a flag that states if it's a service based on what is found in Win32_Service. In Win32_Process it has Parent ID so I'm able to sort and setup the process for each, including services and their children. I'll update my answer with a new method when I'm done with it as I'm trying to make the flow cleaner. As am old school developer, I don't like over coding as most do these days. – Chizl Apr 05 '22 at 13:41
  • @Jimi Thanks, I'll take a look at that as well. – Chizl Apr 05 '22 at 13:43