Sign in to follow this  
Followers 0
Adam9

Check State of Windows Service

7 posts in this topic

I need to check the state of the service. The problem is that technically it has started, but it may be paused. So checking for start/stop states isn't enough.

The MSDN article here says that this function will return the state that I need because it uses information from this structure. I originally borrowed some code from someone on the forums to check the state of the service, but it only checks for started/stopped. And a paused service (which is what I need to check for) is technically started.

Here is my existing servicerunning function:

Func _ServiceRunning($sComputerName, $sServiceName)
   Local $hAdvapi32
   Local $arRet
   Local $hSC
   Local $hService   
   Local $bRunning = 0

   $hAdvapi32 = DllOpen("advapi32.dll")
   If $hAdvapi32 = -1 Then Return 0
   $arRet = DllCall($hAdvapi32, "long", "OpenSCManager", _
                    "str", $sComputerName, _
                    "str", "ServicesActive", _
                    "long", $SC_MANAGER_CONNECT)
   If $arRet[0] <> 0 Then
      $hSC = $arRet[0]
      $arRet = DllCall($hAdvapi32, "long", "OpenService", _
                       "long", $hSC, _
                       "str", $sServiceName, _
                       "long", $SERVICE_INTERROGATE)
      If $arRet[0] <> 0 Then
         $hService = $arRet[0]
         $arRet = DllCall($hAdvapi32, "int", "ControlService", _
                          "long", $hService, _
                          "long", $SERVICE_CONTROL_INTERROGATE, _
                          "str", "")
        $bRunning = $arRet[0]
         DllCall($hAdvapi32, "int", "CloseServiceHandle", "long", $hService)
      EndIf
      DllCall($hAdvapi32, "int", "CloseServiceHandle", "long", $hSC)
   EndIf
   DllClose($hAdvapi32)   
   Return $bRunning
EndFunc

Any ideas on how I can check for the actual state? Thanks!

Share this post


Link to post
Share on other sites



#2 ·  Posted (edited)

After looking at some of the api calls it looks like you should use the QueryServiceStatus API call. In this VB example you can convert it to use in AutoIt pretty easily it looks like. You will want the function ServiceStatus.

Here check out this, I'm sure you will be able to piece it all together.

API Call

Edited by Kerberuz

Kerby

Share this post


Link to post
Share on other sites

You can run:

sc query [servicename] > output.txt

...and check the output text file for PAUSED.

If you use the beta release of AutoIt there is an extension of the Run function that would let you capture the output directly without redirecting to a text file.


Yes yes yes, there it was. Youth must go, ah yes. But youth is only being in a way like it might be an animal. No, it is not just being an animal so much as being like one of these malenky toys you viddy being sold in the streets, like little chellovecks made out of tin and with a spring inside and then a winding handle on the outside and you wind it up grrr grrr grrr and off it itties, like walking, O my brothers. But it itties in a straight line and bangs straight into things bang bang and it cannot help what it is doing. Being young is like being like one of these malenky machines.

Share this post


Link to post
Share on other sites

The sc command does exactly what I need. Unfortunately, this app has to run on Windows versions older than XP :(

I took a look at the VB code and tried porting it, but the array I get back is exactly the same regardless of the state of the service I am checking for.

Array Results:

0

1527358

(Blank)

4

Here's my AutoIt code without the variable declarations:

_ServiceRunning('', 'McShield')
Func _ServiceRunning($sComputerName, $sServiceName)
   Local $hAdvapi32
   Local $arRet
   Local $hSC
   Local $hService   
   Local $bRunning = 0
   Local $status
   
   $hAdvapi32 = DllOpen("advapi32.dll")
   If $hAdvapi32 = -1 Then Return 0
   $arRet = DllCall($hAdvapi32, "long", "OpenSCManager", _
                    "str", $sComputerName, _
                    "str", "ServicesActive", _
                    "long", $SC_MANAGER_CONNECT)
   If $arRet[0] <> 0 Then
      $hSC = $arRet[0]
      $arRet = DllCall($hAdvapi32, "long", "OpenService", _
                       "long", $hSC, _
                       "str", $sServiceName, _
                       "long", $SERVICE_INTERROGATE)
      If $arRet[0] <> 0 Then
         $hService = $arRet[0]
         $arRet = DllCall($hAdvapi32, "long", "QueryServiceStatus", "long", $hSC, "str", 'McShield', "long", $SERVICE_QUERY_STATUS)
        $bRunning = $arRet[0]
        _ArrayDisplay($arRet, 'hi')
                   ;MsgBox(4096,'Debug', $bRunning)
         DllCall($hAdvapi32, "int", "CloseServiceHandle", "long", $hService)
      EndIf
      DllCall($hAdvapi32, "int", "CloseServiceHandle", "long", $hSC)
   EndIf
   DllClose($hAdvapi32)   

EndFunc

Here's the relevant VB code:

Public Function ServiceStatus(ComputerName As String, ServiceName As String) As String
    Dim ServiceStat As SERVICE_STATUS
    Dim hSManager As Long
    Dim hService As Long
    Dim hServiceStatus As Long

    ServiceStatus = ""
    hSManager = OpenSCManager(ComputerName, SERVICES_ACTIVE_DATABASE, SC_MANAGER_ALL_ACCESS)
    If hSManager <> 0 Then
        hService = OpenService(hSManager, ServiceName, SERVICE_ALL_ACCESS)
        If hService <> 0 Then
            hServiceStatus = QueryServiceStatus(hService, ServiceStat)
            If hServiceStatus <> 0 Then
                Select Case ServiceStat.dwCurrentState
                Case SERVICE_STOPPED
                    ServiceStatus = "Stopped"
                Case SERVICE_START_PENDING
                    ServiceStatus = "Start Pending"
                Case SERVICE_STOP_PENDING
                    ServiceStatus = "Stop Pending"
                Case SERVICE_RUNNING
                    ServiceStatus = "Running"
                Case SERVICE_CONTINUE_PENDING
                    ServiceStatus = "Coninue Pending"
                Case SERVICE_PAUSE_PENDING
                    ServiceStatus = "Pause Pending"
                Case SERVICE_PAUSED
                    ServiceStatus = "Paused"
                End Select
            End If
            CloseServiceHandle hService
        End If
        CloseServiceHandle hSManager
    End If
End Function

Share this post


Link to post
Share on other sites

Here you go. You need the latest beta for DllStruct support.

Opt("MustDeclareVars", 1)

Global Const $SC_MANAGER_CONNECT            = 0x0001
Global Const $SERVICE_QUERY_STATUS          = 0x0004
; Service State -- for CurrentState
Global Const $SERVICE_STOPPED               = 0x00000001
Global Const $SERVICE_START_PENDING         = 0x00000002
Global Const $SERVICE_STOP_PENDING          = 0x00000003
Global Const $SERVICE_RUNNING               = 0x00000004
Global Const $SERVICE_CONTINUE_PENDING      = 0x00000005
Global Const $SERVICE_PAUSE_PENDING         = 0x00000006
Global Const $SERVICE_PAUSED                = 0x00000007

ConsoleWrite(_ServiceCurrentState(@ComputerName, "spooler") & @LF)

Func _ServiceCurrentState($sComputerName, $sServiceName)
    Local $hAdvapi32
    Local $hSCM
    Local $hService
    Local $aDllRet
    Local $SERVICE_STATUS
    Local $nState = 0
    
    $hAdvapi32 = DllOpen("advapi32.dll")
    If $hAdvapi32 = -1 Then Return 0
    $aDllRet = DllCall($hAdvapi32, "long", "OpenSCManager", _
        "str", $sComputerName, _
        "str", "ServicesActive", _
        "long", $SC_MANAGER_CONNECT)
    If $aDllRet[0] <> 0 Then
        $hSCM = $aDllRet[0]
        ConsoleWrite("hSCM=" & $hSCM & @LF)
        $aDllRet = DllCall($hAdvapi32, "long", "OpenService", _
            "long", $hSCM, _
            "str", $sServiceName, _
            "long", $SERVICE_QUERY_STATUS)
        If $aDllRet[0] <> 0 Then
            $hService = $aDllRet[0]
            ConsoleWrite("hService=" & $hService & @LF)
            $SERVICE_STATUS = DllStructCreate("dword;dword;dword;dword;dword;dword;dword")
            If Not @error Then
                $aDllRet = DllCall($hAdvapi32, "int", "QueryServiceStatus", _
                    "long", $hService, _
                    "ptr", DllStructGetPtr($SERVICE_STATUS))
                If Not @error And $aDllRet[0] > 0 Then $nState = DllStructGetData($SERVICE_STATUS, 2)
                DllStructDelete($SERVICE_STATUS)
            EndIf
            DllCall($hAdvapi32, "int", "CloseServiceHandle", "long", $hService)
        EndIf
        DllCall($hAdvapi32, "int", "CloseServiceHandle", "long", $hSCM)
    EndIf
    DllClose($hAdvapi32)
    Return $nState
EndFunc

Share this post


Link to post
Share on other sites

Hello,

The sc command does exactly what I need. Unfortunately, this app has to run on Windows versions older than XP 

If your app will run on 2000 or NT, you can use psservice from the pstools ( http://www.sysinternals.com )

the syntax yo query the state of a service is : psservice query process_name


Share this post


Link to post
Share on other sites

Sylvanie: Thanks for the tip, but I got the API calls working.

Sum: Thanks! I integrated the code and it worked perfectly.

Share this post


Link to post
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
Sign in to follow this  
Followers 0