Click here to Skip to main content
15,881,281 members
Articles / Programming Languages / C#
Article

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

Rate me:
Please Sign up or sign in to vote.
4.63/5 (16 votes)
27 Jul 2008CPOL2 min read 100.7K   4K   47   10
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)


Written By
Software Developer StarLIMS
Israel Israel
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
SuggestionFor anyone requesting remote functionality Pin
corte12-Nov-14 9:02
corte12-Nov-14 9:02 
GeneralMy vote of 4 Pin
SATHERahul198922-Nov-12 0:08
SATHERahul198922-Nov-12 0:08 
QuestionWhat about remote servers? Pin
Member 960576716-Nov-12 10:19
Member 960576716-Nov-12 10:19 
GeneralMy vote of 5 Pin
poLedu17-Jan-12 2:51
poLedu17-Jan-12 2:51 
Question5 is fair enaugh I think Pin
poLedu17-Jan-12 2:47
poLedu17-Jan-12 2:47 
GeneralMy vote of 4 Pin
engineer4213-Sep-10 22:58
engineer4213-Sep-10 22:58 
GeneralDoesn't work for me :( [modified] Pin
taralex12-Dec-08 3:08
taralex12-Dec-08 3:08 
GeneralThat's OK ! Pin
eusebe22-Oct-08 22:25
eusebe22-Oct-08 22:25 
GeneralQuestion about methods using "Win32_Service.Name='{0}'" Pin
eusebe22-Oct-08 22:03
eusebe22-Oct-08 22:03 
GeneralSuggestion: Pin
Uros Calakovic28-Aug-08 0:02
Uros Calakovic28-Aug-08 0:02 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.