Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / Languages / C#

Using WMI to manipulate services (Install, Uninstall, Start, Pause etc…)

4.63/5 (16 votes)
27 Jul 2008CPOL2 min read 2   4K  
Perform all the available actions on services simply by using WMI.

Image 1

Introduction

Recently, I was asked to assemble a class which will handle many of the Windows services operations. After hours of going through Google, trying to find some help, all I got was some very complicated APIs, writing their declarations alone was so tedious that I left that solution immediately.

Another solutions was to use the Visual Studio Setup and Deployment Wizard (which is very wasteful), or to use the InstallUtil (supplied with the .NET framework), or sc.exe (which is nice, but still external).

Finally, I decided to use WMI, which stands for Windows Management Instrumentation. These classes provide access to a lot of Windows management devices, including services. The only catch is that it is mainly designed for VBScript, so I had to make some changes in order for it to fit here.

General Information

WMI includes a class named Win32_Service (more about this class can be found here: MSDN). In my class, I had to used this for two objects: for the Services Manager, and for the service itself. The use of the Services Manager is mainly for installing the services (because we need to create a new service in it); after that (when the service is installed), I work with the service itself.

Part I: Installing the Service

Say you have the same problem I have – you have an exe file (which is the service), and you want to install it. Your options are:

  1. Create a setup project (Visual Studio) – which I think is too much.
  2. Use InstallUtil.exe – external.
  3. Use sc.exe – nicer than InstallUtil (at least, I think so), but again – external.

So here is another, better way, using the WMI:

C#
public static ReturnValue InstallService(string svcName, string svcDispName,
       string svcPath, ServiceType svcType, 
       OnError errHandle, StartMode svcStartMode,
       bool interactWithDesktop, string svcStartName, string svcPassword,
       string loadOrderGroup, string[] loadOrderGroupDependencies, 
       string[] svcDependencies) 
{ 
    ManagementClass mc = new ManagementClass("Win32_Service"); 
    ManagementBaseObject inParams = mc.GetMethodParameters("create"); 
    inParams["Name"] = svcName; 
    inParams["DisplayName"] = svcDispName; 
    inParams["PathName"] = svcPath; 
    inParams["ServiceType"] = svcType; 
    inParams["ErrorControl"] = errHandle; 
    inParams["StartMode"] = svcStartMode.ToString(); 
    inParams["DesktopInteract"] = interactWithDesktop; 
    inParams["StartName"] = svcStartName; 
    inParams["StartPassword"] = svcPassword; 
    inParams["LoadOrderGroup"] = loadOrderGroup; 
    inParams["LoadOrderGroupDependencies"] = loadOrderGroupDependencies; 
    inParams["ServiceDependencies"] = svcDependencies; 
    try 
    { 
        ManagementBaseObject outParams = mc.InvokeMethod("create", inParams, null); 
        return (ReturnValue)Enum.Parse(typeof(ReturnValue),
        outParams["ReturnValue"].ToString()); 
    } 
    catch (Exception ex) 
    { throw ex; } 
}

Here, we use the Win32_Service to add a new service to the Services Manager. (All the enums are declared in the code, I don’t want to puff this article too much.)

Part II: Doing All Other Operations on the Service

So, yes, we only use the Services Manager when we want to install a new service (or iterate through all the services), but now, we want to have all kinds of actions with our service. Here we’ll use this line, which will eventually give us the control for the service:

C#
string objPath = string.Format("Win32_Service.Name='{0}'", svcName);
using (ManagementObject service = new ManagementObject(new ManagementPath(objPath)))
{…}
...

Here, “service” holds to an instance of our service, and now, all we have left is to invoke the methods on this (you can find all the methods in the above URL).

C#
public static ReturnValue UninstallService(string svcName)
{
    string objPath = string.Format("Win32_Service.Name='{0}'", svcName);
    using (ManagementObject service = new ManagementObject(new ManagementPath(objPath)))
    {
        try
        {
            ManagementBaseObject outParams = service.InvokeMethod("delete", null,  null);
            return (ReturnValue)Enum.Parse(typeof(ReturnValue),
            outParams["ReturnValue"].ToString());
        }
        catch (Exception ex)
        {
            if (ex.Message.ToLower().Trim() == "not found" || ex.GetHashCode() == 41149443)
                return ReturnValue.ServiceNotFound;
            else
                throw ex;
        }
    }
}

public static ReturnValue StartService(string svcName)
{
    string objPath = string.Format("Win32_Service.Name='{0}'", svcName);
    using (ManagementObject service = new ManagementObject(new ManagementPath(objPath)))
    {
        try
        {
            ManagementBaseObject outParams = service.InvokeMethod("StartService",
                null, null);
            return (ReturnValue)Enum.Parse(typeof(ReturnValue),
            outParams["ReturnValue"].ToString());
        }
        catch (Exception ex)
        {
            if (ex.Message.ToLower().Trim() == "not found" || ex.GetHashCode() == 41149443)
                return ReturnValue.ServiceNotFound;
            else
                throw ex;
        }
    }
}

public static ReturnValue StopService(string svcName)
{
    string objPath = string.Format("Win32_Service.Name='{0}'", svcName);
    using (ManagementObject service = new ManagementObject(new ManagementPath(objPath)))
    {
        try
        {
            ManagementBaseObject outParams = service.InvokeMethod("StopService",
                null, null);
            return (ReturnValue)Enum.Parse(typeof(ReturnValue),
            outParams["ReturnValue"].ToString());
        }
        catch (Exception ex)
        {
            if (ex.Message.ToLower().Trim() == "not found" || ex.GetHashCode() == 41149443)
                return ReturnValue.ServiceNotFound;
            else
                throw ex;
        }
    }
}

public static ReturnValue ResumeService(string svcName)
{
    string objPath = string.Format("Win32_Service.Name='{0}'", svcName);
    using (ManagementObject service = new ManagementObject(new ManagementPath(objPath)))
    {
        try
        {
            ManagementBaseObject outParams = service.InvokeMethod("ResumeService",
                null, null);
            return (ReturnValue)Enum.Parse(typeof(ReturnValue),
                outParams["ReturnValue"].ToString());
        }
        catch (Exception ex)
        {
            if (ex.Message.ToLower().Trim() == "not found" || ex.GetHashCode() == 41149443)
                return ReturnValue.ServiceNotFound;
            else
                throw ex;
        }
    }
}

public static ReturnValue PauseService(string svcName)
{
    string objPath = string.Format("Win32_Service.Name='{0}'", svcName);
    using (ManagementObject service = new ManagementObject(new ManagementPath(objPath)))
    {
        try
        {
            ManagementBaseObject outParams = service.InvokeMethod("PauseService",
                null, null);
            return (ReturnValue)Enum.Parse(typeof(ReturnValue),
                outParams["ReturnValue"].ToString());
        }
        catch (Exception ex)
        {
            if (ex.Message.ToLower().Trim() == "not found" || ex.GetHashCode() == 41149443)
                return ReturnValue.ServiceNotFound;
            else
                throw ex;
        }
    }
}

public static ReturnValue ChangeStartMode(string svcName, StartMode startMode)
{
    string objPath = string.Format("Win32_Service.Name='{0}'", svcName);
    using (ManagementObject service = new ManagementObject(new ManagementPath(objPath)))
    {
        ManagementBaseObject inParams = service.GetMethodParameters("ChangeStartMode");
        inParams["StartMode"] = startMode.ToString();
        try
        {
            ManagementBaseObject outParams = service.InvokeMethod("ChangeStartMode",
                inParams, null);
            return (ReturnValue)Enum.Parse(typeof(ReturnValue),
                outParams["ReturnValue"].ToString());
        }
        catch (Exception ex)
        { throw ex; }
    }
}

public static bool IsServiceInstalled(string svcName)
{
    string objPath = string.Format("Win32_Service.Name='{0}'", svcName);
    using (ManagementObject service = new ManagementObject(new ManagementPath(objPath)))
    {
        try
        {
            ManagementBaseObject outParams = service.InvokeMethod("InterrogateService",
                null, null);
            return true;
        }
        catch (Exception ex)
        {
            if (ex.Message.ToLower().Trim() == "not found" || ex.GetHashCode() == 41149443)
                return false;
            else
                throw ex;
        }    
    }
}

public static ServiceState GetServiceState(string svcName)
{
    ServiceState toReturn = ServiceState.Stopped;
    string _state = string.Empty;
    string objPath = string.Format("Win32_Service.Name='{0}'", svcName);
    using (ManagementObject service = new ManagementObject(new ManagementPath(objPath)))
    {
        try
        {
            _state = service.Properties["State"].Value.ToString().Trim();
            switch (_state)
            {
            case "Running":
                toReturn = ServiceState.Running;
                break;
            case "Stopped":
                toReturn = ServiceState.Stopped;
                break;
            case "Paused":
                toReturn = ServiceState.Paused;
                break;
            case "Start Pending":
                toReturn = ServiceState.StartPending;
                break;
            case "Stop Pending":
                toReturn = ServiceState.StopPending;
                break;
            case "Continue Pending":
                toReturn = ServiceState.ContinuePending;
                break;
            case "Pause Pending":
                toReturn = ServiceState.PausePending;
                break;
            }
        }
        catch (Exception ex)
        { throw ex; }
    }
    return toReturn;
}

public static bool CanStop(string svcName)
{
    string objPath = string.Format("Win32_Service.Name='{0}'", svcName);
    using (ManagementObject service = new ManagementObject(new ManagementPath(objPath)))
    {
        try
        {
            return bool.Parse(service.Properties["AcceptStop"].Value.ToString());
        }
        catch
        {
            return false;
        }
    }
}

public static bool CanPauseAndContinue(string svcName)
{
    string objPath = string.Format("Win32_Service.Name='{0}'", svcName);
    using (ManagementObject service = new ManagementObject(new ManagementPath(objPath)))
    {
        try
        {
            return bool.Parse(service.Properties["AcceptPause"].Value.ToString());
        }
        catch
        {
            return false;
        }
    }
}

public static int GetProcessId(string svcName)
{
    string objPath = string.Format("Win32_Service.Name='{0}'", svcName);
    using (ManagementObject service = new ManagementObject(new ManagementPath(objPath)))
    {
        try
        {
            return int.Parse(service.Properties["ProcessId"].Value.ToString());
        }
        catch
        {
            return 0;
        }
    }
}

public static string GetPath(string svcName)
{
    string objPath = string.Format("Win32_Service.Name='{0}'", svcName);
    using (ManagementObject service = new ManagementObject(new ManagementPath(objPath)))
    {
        try
        {
            return service.Properties["PathName"].Value.ToString();
        }
        catch
        {
            return string.Empty;
        }
    }
}

Conclusion

Well, this is all kind of a mess, but if you'll look closer — it's very much the same templates for all... just get the object, and do whatever you want on it.

You can find many of the object's properties using:

C#
foreach (PropertyData pd in service.Properties)
  if (pd.Value!= null)
    MessageBox.Show(pd.Name + " = " + pd.Value.ToString());

I hope this article will be useful to many of you. I think this is the first mini-comprehensive guide for handling services using the WMI.

Any review is welcome. Thanks for reading.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)