Jump to content

Windows Services UDF


engine
 Share

Recommended Posts

I recently needed a way to enumerate services, I found this UDF but when running _Service_Enum the 300 ms delay was too long for me so I went and optimized the code now it runs over 10x quicker (~20ms) I may update the other functions if I have a use for them.

Func _Service_Enum($iServiceType, $iServiceState = $SERVICE_STATE_ALL, $sLoadOrderGroup = Default, $sComputerName = "")
    ;Local $SC_ENUM_PROCESS_INFO = 0
    Local $tLoadOrderGroup, $iErr
    Local $hSCM, $uEBuf, $tEBuf, $avEnumSvc

    $tLoadOrderGroup = DllStructCreate("char[" & Number($sLoadOrderGroup <> Default) * (StringLen($sLoadOrderGroup) + 1) & "]")
    DllStructSetData($tLoadOrderGroup, 1, $sLoadOrderGroup)

    ;open service manager
    $hSCM = OpenSCManager($sComputerName, $SC_MANAGER_ENUMERATE_SERVICE)
    ; Determine needed size of the struct in bytes
    $avEnumSvc = DllCall("advapi32.dll", "int", "EnumServicesStatusEx", _
            "hwnd", $hSCM, _
            "dword", $SC_ENUM_PROCESS_INFO, _
            "dword", $iServiceType, _
            "dword", $iServiceState, _
            "ptr", 0, _
            "dword", 0, _
            "dword*", 0, _
            "dword*", 0, _
            "dword*", 0, _
            "ptr", DllStructGetPtr($tLoadOrderGroup))

    ; Load buffer with Service data
    $uEBuf = DllStructCreate("ubyte[" & $avEnumSvc[7] & "]") ;ubyte buffer

    $avEnumSvc = DllCall("advapi32.dll", "int", "EnumServicesStatusEx", _
            "hwnd", $hSCM, _
            "dword", $SC_ENUM_PROCESS_INFO, _
            "dword", $iServiceType, _
            "dword", $iServiceState, _
            "ptr", DllStructGetPtr($uEBuf), _        ;5-lpServices
            "dword", DllStructGetSize($uEBuf), _ ;6-cbBufSize
            "dword*", 0, _                       ;7-pcbBytesNeeded
            "dword*", 0, _                       ;8-lpServicesReturned
            "dword*", 0, _                       ;9-lpResumeHandle
            "ptr", DllStructGetPtr($tLoadOrderGroup)) ;10-pszGroupName

    ; Get last error and close service control manager database handle
    If $avEnumSvc[0] = 0 Then $iErr = _WinAPI_GetLastError()
    CloseServiceHandle($hSCM)


    Local $asSvcsStatus[$avEnumSvc[8] + 1][11] = [[$avEnumSvc[8], 11]] ;Prepare return Array

    ; Decode the ubyte structure

    For $i = 1 To $avEnumSvc[8]
        $tEBuf = DllStructCreate("uint_ptr[2];dword[9]", $avEnumSvc[5] + (DllStructGetSize($tEBuf) * ($i - 1))) ;Prepare buffer increment pointer by struct sz

        For $k = 0 To 1
            $asSvcsStatus[$i][$k] = DllStructGetData(DllStructCreate("char[257]", DllStructGetData($tEBuf, 1, $k + 1)), 1) ;fill char array with info from ptr
        Next

        For $k = 1 To UBound($asSvcsStatus, 2) - 2
            $asSvcsStatus[$i][$k + 1] = DllStructGetData($tEBuf, 2, $k)
        Next

    Next

    Return SetError($iErr, 0, $asSvcsStatus)
EndFunc   ;==>_Service_Enum

I reworked the parsing to use less temporary variables and less copying, Should be a drop in replacement.

Edited by Bilgus
fixed typo in buffer name
Link to comment
Share on other sites

  • 2 years later...

Sorry for the Nekro.

This is the best services UDF I have seen.

I used it with great success to fix a bad application that was growing out of control with temp files.

I have a new project I am working on right now, and unlike last time I used it I am not running it local, but instead trying to start/stop/query services on a remote server as I have a cluster of servers that need services stopped/started in a special order.

 

I made the code, and now in testing it is not working.

I get an Error Code of 6 for @Error for Service_Stop and I am a admin on the remote server.

I am not sure if its security/permissions issues, or something else.

 

#Edit#

Still works - We had a crazy server name and I was missing a letter.

:)

 

Edited by ViciousXUSMC
Link to comment
Share on other sites

  • 1 year later...
  • 1 year later...
  • 1 year later...

I cannot figure out, why syntax check post this errors when I include this UDF

 

; Includes
#include <MsgBoxConstants.au3>
#include <Services.au3>
#include <SecurityConstants.au3>

"C:\Program Files (x86)\AutoIt3\Include\Services.au3"(481,61) : warning: $RIGHTS_DELETE: possibly used before declaration.
    $hService = OpenService($hSC, $sServiceName, $RIGHTS_DELETE)
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^
"C:\Program Files (x86)\AutoIt3\Include\Services.au3"(481,61) : error: $RIGHTS_DELETE: undeclared global variable.
    $hService = OpenService($hSC, $sServiceName, $RIGHTS_DELETE)
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^

 

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...