enumservicesstatus (advapi32)
Last changed: -74.56.93.131

.
Summary
Enumerates services in the specified service control manager database. The name and status of each service are provided, long with additional data based on the specified information level.

C# Signature:

      [DllImport("advapi32.dll", SetLastError = true, CharSet = CharSet.Auto)]
      static extern bool EnumServicesStatusEx(IntPtr hSCManager,
      int infoLevel, int dwServiceType,
      int dwServiceState, IntPtr lpServices, UInt32 cbBufSize,
      out uint pcbBytesNeeded, out uint lpServicesReturned,
      ref uint lpResumeHandle, string pszGroupName);

VB Signature:

TODO

User-Defined Types:

(see example code below).

Alternative Managed API:

There is no known alternative managed API as of .Net 3.5/

Notes:

This works on both 32 bit and 64 bit machines.

Tips & Tricks:

As usual when doing pinvoke operations, watch out for 64 bit vs 32 bit and packing boundaries.

Sample Code:

    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Runtime.InteropServices;
    using System.Security.Permissions;

      [SecurityPermission(SecurityAction.LinkDemand, UnmanagedCode = true)]
      internal static ENUM_SERVICE_STATUS_PROCESS[] GetServices()
     {
     List<ENUM_SERVICE_STATUS_PROCESS> result = new List<ENUM_SERVICE_STATUS_PROCESS>();

     IntPtr handle = IntPtr.Zero;
     IntPtr buf = IntPtr.Zero;
     try
        {
        handle = OpenSCManager(null, null, (int)ServiceControlManagerType.SC_MANAGER_ALL_ACCESS);
        if (handle != IntPtr.Zero)
           {
           uint iBytesNeeded = 0;
           uint iServicesReturned = 0;
           uint iResumeHandle = 0;

           ENUM_SERVICE_STATUS_PROCESS infoLevel = new ENUM_SERVICE_STATUS_PROCESS();
           if (!EnumServicesStatusEx(handle, SC_ENUM_PROCESS_INFO, (int)ServiceType.SERVICE_WIN32, (int)ServiceStateRequest.SERVICE_STATE_ALL, IntPtr.Zero, 0, out iBytesNeeded, out iServicesReturned, ref iResumeHandle, null))
          {
          // allocate our memory to receive the data for all the services (including the names)
          buf = Marshal.AllocHGlobal((int)iBytesNeeded);

          if (!EnumServicesStatusEx(handle, SC_ENUM_PROCESS_INFO, (int)ServiceType.SERVICE_WIN32, (int)ServiceStateRequest.SERVICE_STATE_ALL, buf, iBytesNeeded, out iBytesNeeded, out iServicesReturned, ref iResumeHandle, null))
             throw new Win32Exception(Marshal.GetLastWin32Error());

          ENUM_SERVICE_STATUS_PROCESS serviceStatus;

          // check if 64 bit system which has different pack sizes
          if (IntPtr.Size == 8)
             {
             long pointer = buf.ToInt64();
             for (int i = 0; i < (int)iServicesReturned; i++)
            {
            serviceStatus = (ENUM_SERVICE_STATUS_PROCESS)Marshal.PtrToStructure(new IntPtr(pointer),
               typeof(ENUM_SERVICE_STATUS_PROCESS));
            result.Add(serviceStatus);

            // incremement by sizeof(ENUM_SERVICE_STATUS_PROCESS) allow Packing of 8
            pointer += ENUM_SERVICE_STATUS_PROCESS.SizePack8;
            }

             }
          else
             {
             int pointer = buf.ToInt32();
             for (int i = 0; i < (int)iServicesReturned; i++)
            {
            serviceStatus = (ENUM_SERVICE_STATUS_PROCESS)Marshal.PtrToStructure(new IntPtr(pointer),
               typeof(ENUM_SERVICE_STATUS_PROCESS));
            result.Add(serviceStatus);

            // incremement by sizeof(ENUM_SERVICE_STATUS_PROCESS) allow Packing of 4
            pointer += ENUM_SERVICE_STATUS_PROCESS.SizePack4;
            }
             }
          }
           }
        }
     catch(Exception e)
        {
        ;
        }
     finally
        {
        if (handle != IntPtr.Zero)
           CloseServiceHandle(handle);

        if (buf != IntPtr.Zero)
           Marshal.FreeHGlobal(buf);
        }

     return result.ToArray();
     }

      private const int SC_ENUM_PROCESS_INFO = 0;

      [DllImport("advapi32.dll", SetLastError = true, CharSet = CharSet.Auto)]
      private static extern bool EnumServicesStatusEx(IntPtr hSCManager,
      int infoLevel, int dwServiceType,
      int dwServiceState, IntPtr lpServices, UInt32 cbBufSize,
      out uint pcbBytesNeeded, out uint lpServicesReturned,
      ref uint lpResumeHandle, string pszGroupName);

      [StructLayout(LayoutKind.Sequential, Pack = 4)]
      internal struct ENUM_SERVICE_STATUS_PROCESS
     {
     internal static readonly int SizePack4 = Marshal.SizeOf(typeof(ENUM_SERVICE_STATUS_PROCESS));

     /// <summary>
     /// sizeof(ENUM_SERVICE_STATUS_PROCESS) allow Packing of 8 on 64 bit machines
     /// </summary>
     internal static readonly int SizePack8 = Marshal.SizeOf(typeof(ENUM_SERVICE_STATUS_PROCESS)) + 4;

     [MarshalAs(System.Runtime.InteropServices.UnmanagedType.LPWStr)]
     internal string pServiceName;

     [MarshalAs(System.Runtime.InteropServices.UnmanagedType.LPWStr)]
     internal string pDisplayName;

     internal SERVICE_STATUS_PROCESS ServiceStatus;
     }

      [StructLayout(LayoutKind.Sequential)]
      internal struct SERVICE_STATUS_PROCESS
     {
     public int serviceType;
     public int currentState;
     public int controlsAccepted;
     public int win32ExitCode;
     public int serviceSpecificExitCode;
     public int checkPoint;
     public int waitHint;
     public int processId;
     public int serviceFlags;
     }

      private enum ServiceType { SERVICE_KERNEL_DRIVER = 0x1, SERVICE_FILE_SYSTEM_DRIVER = 0x2, SERVICE_WIN32_OWN_PROCESS = 0x10, SERVICE_WIN32_SHARE_PROCESS = 0x20, SERVICE_INTERACTIVE_PROCESS = 0x100, SERVICETYPE_NO_CHANGE = SERVICE_NO_CHANGE, SERVICE_WIN32 = (SERVICE_WIN32_OWN_PROCESS | SERVICE_WIN32_SHARE_PROCESS) }

      private enum ServiceStateRequest { SERVICE_ACTIVE = 0x1, SERVICE_INACTIVE = 0x2, SERVICE_STATE_ALL = (SERVICE_ACTIVE | SERVICE_INACTIVE) }

      private enum ServiceControlManagerType { SC_MANAGER_CONNECT = 0x1, SC_MANAGER_CREATE_SERVICE = 0x2, SC_MANAGER_ENUMERATE_SERVICE = 0x4, SC_MANAGER_LOCK = 0x8, SC_MANAGER_QUERY_LOCK_STATUS = 0x10, SC_MANAGER_MODIFY_BOOT_CONFIG = 0x20, SC_MANAGER_ALL_ACCESS = STANDARD_RIGHTS_REQUIRED | SC_MANAGER_CONNECT | SC_MANAGER_CREATE_SERVICE | SC_MANAGER_ENUMERATE_SERVICE | SC_MANAGER_LOCK | SC_MANAGER_QUERY_LOCK_STATUS | SC_MANAGER_MODIFY_BOOT_CONFIG }

Documentation