views:

103

answers:

1

I have a Win32 program which I can direct to monitor another Win32 process.

I want to find a way for the monitoring program to determine if the monitored process is running as a Win32 service.

Not all services run as SYSTEM and not all services have services.exe as a direct parent, so I don't regard these obvious techniques as being robust enough.

To be clear, what I'm looking for is a way to write the function:

bool isService(HANDLE aProcessHandle) { ... }

A: 

You can do this easily using WMI. I realize that you did not specify C#, but the WMI api is available on all platforms in quite similar fashion.

First we need an object shaped like a Win32_Service

public class Win32_Service
{
    public Win32_Service(ManagementBaseObject obj)
    {

        AcceptPause = (bool)(obj["AcceptPause"] ?? false);
        AcceptStop = (bool)(obj["AcceptStop"] ?? false);
        Caption = (string)(obj["Caption"] ?? "");
        CheckPoint = (UInt32)(obj["CheckPoint"] ?? 0);
        CreationClassName = (string)(obj["CreationClassName"] ?? "");
        Description = (string)(obj["Description"] ?? "");
        DesktopInteract = (bool)(obj["DesktopInteract"] ?? false);
        DisplayName = (string)(obj["DisplayName"] ?? "");
        ErrorControl = (string)(obj["ErrorControl"] ?? "");
        ExitCode = (UInt32)(obj["ExitCode"] ?? 0);
        InstallDate = (DateTime)(obj["InstallDate"] ?? DateTime.MinValue);
        Name = (string)(obj["Name"] ?? "");
        PathName = (string)(obj["PathName"] ?? "");
        ProcessId = (UInt32)(obj["ProcessId"] ?? 0);
        ServiceSpecificExitCode = (UInt32)(obj["ServiceSpecificExitCode"] ?? 0);
        ServiceType = (string)(obj["ServiceType"] ?? "");
        Started = (bool)(obj["Started"] ?? false);
        StartMode = (string)(obj["StartMode"] ?? "");
        StartName = (string)(obj["StartName"] ?? "");
        State = (string)(obj["State"] ?? "");
        Status = (string)(obj["Status"] ?? "");
        SystemCreationClassName = (string)(obj["SystemCreationClassName"] ?? "");
        SystemName = (string)(obj["SystemName"] ?? "");
        TagId = (UInt32)(obj["TagId"] ?? 0);
        WaitHint = (UInt32)(obj["WaitHint"] ?? 0);
    }
    bool AcceptPause;
    bool AcceptStop;
    string Caption;
    UInt32 CheckPoint;
    string CreationClassName;
    string Description;
    bool DesktopInteract;
    string DisplayName;
    string ErrorControl;
    UInt32 ExitCode;
    DateTime InstallDate;
    string Name;
    string PathName;
    UInt32 ProcessId;
    UInt32 ServiceSpecificExitCode;
    string ServiceType;
    bool Started;
    string StartMode;
    string StartName;
    string State;
    string Status;
    string SystemCreationClassName;
    string SystemName;
    UInt32 TagId;
    UInt32 WaitHint;
};

Now we query WMI for services. Here I just pull all services. If you have more specific criteria, simply modify the query "Select * from Win32_Service"

var services = new System.Collections.Generic.List<Win32_Service>();
using (ManagementObjectSearcher searcher = new ManagementObjectSearcher("Select * from Win32_Service"))
{
    using (ManagementObjectCollection results = searcher.Get())
    {
        foreach (ManagementObject obj in results)
        {
            services.Add(new Win32_Service(obj));
        }
    }
}

Now you can use Linq to query services.

Reference: http://msdn.microsoft.com/en-us/library/ms974579.aspx

Sky Sanders
I'm not sure how I can use this information to write:bool isService(HANDLE aProcessHandle) { ... }Would you elaborate?
quietdragon
@quiet - You asked how to determine if a particular process is running as a service. I provided an example of querying WMI for services, in this case, all services, which you can look for your process name. Alternatively you may be more specific in the query and search explicitly for your target. If it is returned, then it is running as a service. What you do with that information is up to you. ;-) I would suggest using this as a reference for writing some simple WMI code on your platform, c++?. Get a `processId` using your `HANDLE` and compare with the WMI results?
Sky Sanders
@quiet - http://www.codeproject.com/KB/threads/GettingProcessID.aspx
Sky Sanders
Ok. Thanks for the direction. I can get some more clues from:http://technet.microsoft.com/en-us/library/ee198746.aspx
quietdragon
C++ examples for calling WMI are available from here:http://msdn.microsoft.com/en-us/library/aa390423%28v=VS.85%29.aspx
quietdragon