Enumerate services

Share your advanced PureBasic knowledge/code with the community.
TeddyLM
Enthusiast
Enthusiast
Posts: 133
Joined: Wed Apr 30, 2003 2:04 pm
Location: Germany (French expat)

Enumerate services

Post by TeddyLM »

Hello
Needed this for Monitoring purposes.
Maybe it can be of use for someone else.

Code: Select all

#SC_ENUM_PROCESS_INFO = 0
#SERVICE_QUERY_CONFIG = 1
;SERVICETYPE
#SERVICE_KERNEL_DRIVER = $1
#SERVICE_FILE_SYSTEM_DRIVER = $2
#SERVICE_RECOGNIZER_DRIVER = $8
#SERVICE_DRIVER = #SERVICE_KERNEL_DRIVER|#SERVICE_FILE_SYSTEM_DRIVER|#SERVICE_RECOGNIZER_DRIVER 
#SERVICE_WIN32_OWN_PROCESS = $10
#SERVICE_WIN32_SHARE_PROCESS = $20
#SERVICE_WIN32 = #SERVICE_WIN32_OWN_PROCESS|#SERVICE_WIN32_SHARE_PROCESS
;SERVICESTATE
#SERVICE_ACTIVE = 1 
#SERVICE_INACTIVE = 2 
#SERVICE_STATE_ALL = 3 

Structure SERVICE_STATUS_PROCESS
    dwServiceType.l
    dwCurrentState.l
    dwControlsAccepted.l
    dwWin32ExitCode.l
    dwServiceSpecificExitCode.l
    dwCheckPoint.l
    dwWaitHint.l
    dwProcessId.l
    dwServiceFlags.l
EndStructure

Structure ENUM_SERVICE_STATUS_PROCESS
    lpServiceName.l
    lpDisplayName.l
    ServiceStatus.SERVICE_STATUS_PROCESS
EndStructure

Prototype ProtoESSEx(hSCManager, InfoLevel, dwServiceType, dwServiceState, *lpServices, cbBufSize, pcbBytesNeeded, lpServicesReturned, lpResumeHandle, pszGroupName)
LibNr.i = OpenLibrary(#PB_Any, "advapi32.dll")
If LibNr
    CompilerIf #PB_Compiler_Unicode
        Global EnumServicesStatusEx.ProtoESSEx = GetFunction(LibNr, "EnumServicesStatusExW")
    CompilerElse
        Global EnumServicesStatusEx.ProtoESSEx = GetFunction(LibNr, "EnumServicesStatusExA")
    CompilerEndIf
Else
    MessageRequester("Error", "File advapi32.dll could not be found", 16) : End 
EndIf

;===========================
Procedure.s SVC_GetType(Type.i)
    Result$ = ""
    If Type & #SERVICE_KERNEL_DRIVER :         Result$ + "SERVICE_KERNEL_DRIVER " : EndIf
    If Type & #SERVICE_FILE_SYSTEM_DRIVER :    Result$ + "SERVICE_FILE_SYSTEM_DRIVER " : EndIf
    If Type & #SERVICE_WIN32_OWN_PROCESS :     Result$ + "SERVICE_WIN32_OWN_PROCESS " : EndIf
    If Type & #SERVICE_WIN32_SHARE_PROCESS :   Result$ + "SERVICE_WIN32_SHARE_PROCESS " : EndIf
    ProcedureReturn Result$
EndProcedure        
;===========================
Procedure.s SVC_GetState(State.i)
    Result$ = ""
    Select State
        Case 1 : Result$ = "SERVICE_STOPPED"
        Case 2 : Result$ = "SERVICE_START_PENDING"
        Case 3 : Result$ = "SERVICE_STOP_PENDING"
        Case 4 : Result$ = "SERVICE_RUNNING"
        Case 5 : Result$ = "SERVICE_CONTINUE_PENDING"
        Case 6 : Result$ = "SERVICE_PAUSE_PENDING"
        Case 7 : Result$ = "SERVICE_PAUSED"
    EndSelect
    ProcedureReturn Result$
EndProcedure
;===========================
Procedure.s SVC_GetStartType(Start.i)
    Result$ = ""
    Select Start
        Case 0 : Result$ = "SERVICE_BOOT_START"
        Case 1 : Result$ = "SERVICE_SYSTEM_START"
        Case 2 : Result$ = "SERVICE_AUTO_START"
        Case 3 : Result$ = "SERVICE_DEMAND_START"
        Case 4 : Result$ = "SERVICE_DISABLED"
    EndSelect
    ProcedureReturn Result$
EndProcedure
;===========================
Procedure.s SVC_GetErrorControl(ErrCtrl.i)
    Result$ = ""
    Select ErrCtrl
        Case 0 : Result$ = "SERVICE_ERROR_IGNORE"
        Case 1 : Result$ = "SERVICE_ERROR_NORMAL"
        Case 2 : Result$ = "SERVICE_ERROR_SEVERE"
        Case 3 : Result$ = "SERVICE_ERROR_CRITICAL"
    EndSelect
    ProcedureReturn Result$
EndProcedure
;===========================
Procedure.s SVC_GetDependencies(Offset.i)
    Result$ = ""
    If PeekB(Offset) <> 0
        String$ = PeekS(Offset)
        While String$ <> ""
            Result$ = Result$ + String$ + " "
            CompilerIf #PB_Compiler_Unicode
                Offset = Offset + (Len(String$)+1)*2
            CompilerElse
                Offset = Offset + Len(String$) + 1
            CompilerEndIf
            String$ = PeekS(Offset)
        Wend
    EndIf
    ProcedureReturn Result$
EndProcedure
;===========================
Procedure SVC_GetInfo(GadgetNr.i, Computer$, ServiceType.i, ServiceState.i)    
    hSCM.i = OpenSCManager_(Computer$, #Null, #SC_MANAGER_ENUMERATE_SERVICE|#GENERIC_READ)
    If hSCM
        bufferSize.l = 0
        requiredBufferSize.l = 0
        totalServicesCount.l = 0
        EnumServicesStatusEx(hSCM, #SC_ENUM_PROCESS_INFO, ServiceType, ServiceState, 0, bufferSize, @requiredBufferSize, @totalServicesCount, 0, 0)    
        NbrServices.i = requiredBufferSize/SizeOf(ENUM_SERVICE_STATUS_PROCESS)
        Dim Service.ENUM_SERVICE_STATUS_PROCESS(NbrServices)
        ResumeHandle.l = 0
        bufferSize = requiredBufferSize
        If EnumServicesStatusEx(hSCM, #SC_ENUM_PROCESS_INFO, ServiceType, ServiceState, @Service(0), bufferSize, @requiredBufferSize, @totalServicesCount, @ResumeHandle, 0)
            For Counter.i = 0 To totalServicesCount-1
                ThisServiceName$ = PeekS(Service(Counter)\lpServiceName)
                AddGadgetItem(0, -1, "=====================")
                AddGadgetItem(0, -1, "Service Nr.: " + Str(Counter + 1))
                AddGadgetItem(0, -1, "ServiceName: " + ThisServiceName$)
                AddGadgetItem(0, -1, "DisplayName: " + PeekS(Service(Counter)\lpDisplayName))
                AddGadgetItem(0, -1, "Type: " + SVC_GetType(Service(Counter)\ServiceStatus\dwServiceType))  
                AddGadgetItem(0, -1, "State: " + SVC_GetState(Service(Counter)\ServiceStatus\dwCurrentState))      
                AddGadgetItem(0, -1, "ProcessID: " + Str(Service(Counter)\ServiceStatus\dwProcessId))
                hService.i = OpenService_(hSCM, ThisServiceName$, #SERVICE_QUERY_CONFIG)
                If hService
                     BytesNeeded.l = 0
                     QueryServiceConfig_(hService, #Null, 0, @BytesNeeded)
                     *Buffer = AllocateMemory(BytesNeeded)
                     If *Buffer
                        If QueryServiceConfig_(hService, *Buffer, BytesNeeded, @BytesNeeded)
                            AddGadgetItem(0, -1, "StartType: " + SVC_GetStartType(PeekL(*Buffer+4)))
                            AddGadgetItem(0, -1, "ErrorControl: " + SVC_GetErrorControl(PeekL(*Buffer+8)))
                            AddGadgetItem(0, -1, "BinaryPathName: " + PeekS(PeekL(*Buffer+12)))
                            AddGadgetItem(0, -1, "StartName: " + PeekS(PeekL(*Buffer+28)))
                            AddGadgetItem(0, -1, "Dependencies: " + SVC_GetDependencies(PeekL(*Buffer + 24)))
                        Else
                            MessageRequester("EnumServices", "QueryServiceConfig() failed (error nr. " + Str(GetLastError_()) + ")", 16) : End
                        EndIf
                     EndIf
                     CloseServiceHandle_(hService)
                Else
                    MessageRequester("EnumServices", "OpenService() failed (error nr. " + Str(GetLastError_()) + ")", 16) : End 
                EndIf
            Next
            CloseServiceHandle_(hSCM)
        Else
            MessageRequester("EnumServices", "EnumServicesStatusEx() failed (error nr. " + Str(GetLastError_()) + ")", 16) : End
        EndIf
        FreeArray(Service())
    EndIf
EndProcedure
;===========================
If OpenWindow(0, 0, 0, 800, 600, "EnumServices", #PB_Window_SystemMenu|#PB_Window_ScreenCentered)
    EditorGadget(0, 0, 0, 800, 600)
    SVC_GetInfo(0, "", #SERVICE_WIN32, #SERVICE_STATE_ALL)
    Repeat : Until WaitWindowEvent() = #PB_Event_CloseWindow
EndIf
User avatar
Kwai chang caine
Always Here
Always Here
Posts: 5494
Joined: Sun Nov 05, 2006 11:42 pm
Location: Lyon - France

Re: Enumerate services

Post by Kwai chang caine »

Works well on W7 pro 32 bits
Thanks for sharing 8)
ImageThe happiness is a road...
Not a destination
juror
Enthusiast
Enthusiast
Posts: 232
Joined: Mon Jul 09, 2007 4:47 pm
Location: Courthouse

Re: Enumerate services

Post by juror »

Good on W10 pro x64

Thanks for sharing!
Post Reply