public static IEnumerable<ENUM_SERVICE_STATUS_PROCESS> GetServices( string machineName, string databaseName, AccessFlags accessFlags, // From OpenSCManager ServiceEnumType infoLevel, ServiceType serviceType, ServiceStateRequest serviceStateRequest // From EnumServicesStatusEx ) { List<ENUM_SERVICE_STATUS_PROCESS> results = new List<ENUM_SERVICE_STATUS_PROCESS>(); IntPtr handle = OpenSCManager(machineName, databaseName, accessFlags); if (handle == IntPtr.Zero) { return null; } IntPtr serviceStatusBuffer = IntPtr.Zero; try { uint bytesNeeded = 0; uint servicesReturned = 0; uint resumeHandle = 0; if (!EnumServicesStatusEx(handle, infoLevel, serviceType, serviceStateRequest, IntPtr.Zero, 0, out bytesNeeded, out servicesReturned, ref resumeHandle, null)) { // allocate our memory to receive the data for all the services (including the names) serviceStatusBuffer = Marshal.AllocHGlobal((int)bytesNeeded); if (!EnumServicesStatusEx(handle, infoLevel, serviceType, serviceStateRequest, serviceStatusBuffer, bytesNeeded, out bytesNeeded, out servicesReturned, ref resumeHandle, 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 = serviceStatusBuffer.ToInt64(); for (int i = 0; i < (int)servicesReturned; i++) { serviceStatus = (ENUM_SERVICE_STATUS_PROCESS)Marshal.PtrToStructure(new IntPtr(pointer), typeof(ENUM_SERVICE_STATUS_PROCESS)); results.Add(serviceStatus); // incremement by sizeof(ENUM_SERVICE_STATUS_PROCESS) allow Packing of 8 pointer += ENUM_SERVICE_STATUS_PROCESS.SizePack8; } } else { int pointer = serviceStatusBuffer.ToInt32(); for (int i = 0; i < (int)servicesReturned; i++) { serviceStatus = (ENUM_SERVICE_STATUS_PROCESS)Marshal.PtrToStructure(new IntPtr(pointer), typeof(ENUM_SERVICE_STATUS_PROCESS)); results.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 (serviceStatusBuffer != IntPtr.Zero) { Marshal.FreeHGlobal(serviceStatusBuffer); } } return results; }
private static extern bool EnumServicesStatusEx(IntPtr hSCManager, ServiceEnumType infoLevel, ServiceType dwServiceType, ServiceStateRequest dwServiceState, IntPtr lpServices, UInt32 cbBufSize, out uint pcbBytesNeeded, out uint lpServicesReturned, ref uint lpResumeHandle, string pszGroupName);