shornw Posted February 29, 2012 Share Posted February 29, 2012 (edited) Hi All, Can one of the infinitely better brains out there, suggest a way of delaying the progress of a function while a service stops. I know I can use Sleep() but wondered if there's a more relevant method, as the process is being run accross a network. I tried: Do $svc = _ServiceRunning($server, "Sophos Agent") If $svc = 0 Then ExitLoop Sleep(500) until $svc = 0 but the service reports that it's not running straight away. As the script stops a service, deletes some files then starts the service again, I need it to wait until the service has entered the stopped state before attempting to delete the files. this is what I have so far: Func RWTest() $svc = _ServiceRunning($server, "Sophos Agent") If $svc = 1 Then ;MsgBox(0, $server, "stop service " & $server & " Sophos Agent") _StopService($server, "Sophos Agent") If @error Then MsgBox(16, "Service Control Failure", "The service control failed with error " & @error) Sleep(5000) Else MsgBox(0, $server, "The Sophos Agent service is currently not running") EndIf Sleep(1000) ;$del = FileDelete($path & "*.msg") ;If $del = 0 Then MsgBox(16, "Delete Error", "Files were not deleted") ;MsgBox(0, $server, "Start service " & $server & " Sophos Agent") _StartService($server, "Sophos Agent") If @error Then MsgBox(16, "Service Control Start Failure", "The service control failed with error " & @error) Sleep(2000) $svc = _ServiceRunning($server, "Sophos Agent") If $svc = 1 Then MsgBox(0, "Service Control", "Sophos Agent service is running") Return Else _StartService($server, "Sophos Agent") EndIf EndFunc Edit- Is there any remote process monitoring within AutoIT. This script will be run from various PC's/Servers so I dont really want to use SysInternals or other 3rd party tools. Edited February 29, 2012 by shornw [font='Comic Sans MS']Eagles may soar high but weasels dont get sucked into jet engines[/font] Link to comment Share on other sites More sharing options...
hannes08 Posted February 29, 2012 Share Posted February 29, 2012 Hi shornw, I used the "sc" command for this. With this cmd-line tool you can even access/query/control remote services. Regards,Hannes[spoiler]If you can't convince them, confuse them![/spoiler] Link to comment Share on other sites More sharing options...
shornw Posted February 29, 2012 Author Share Posted February 29, 2012 Hi Hannes,Firstly, thanks for the idea. I don't think I explained myself very well. I can view the runstate and send a stop control, no problem. What I want to do is delay further execution until the service is in a completely stopped state, so that the files to be deleted have no filelocks.if I send a stop command, then query the runstate (the Do / Until attempt), I get an inaccurate response because the service has begun to shutdown so gets reported as not running, although it is in fact still running.My next idea was to monitor the process, but as far as I'm aware ProcessMGmnt() only works locally. As this is going to be run from all sorts of computers I dont want to use 3rd party tools or O/S specific controls.Currently it seems to be OK with Sleep() (very limited testing carried out), but I feel this is too 'rigid' and may not allow for slower network connections / blips etc bearing in mind that this could be run from any part of the UK, unless I use a ridiculously long time, but that would make it unnecessarily slow.Any suggestions gratefully considered [font='Comic Sans MS']Eagles may soar high but weasels dont get sucked into jet engines[/font] Link to comment Share on other sites More sharing options...
funkey Posted February 29, 2012 Share Posted February 29, 2012 Maybe you could use AdlibRegister to periodically check if the service has already stopped. Programming today is a race between software engineers striving tobuild bigger and better idiot-proof programs, and the Universetrying to produce bigger and better idiots.So far, the Universe is winning. Link to comment Share on other sites More sharing options...
shornw Posted February 29, 2012 Author Share Posted February 29, 2012 I'd still hit the problem of incorrect reporting between sending the stop control and the process actually terminating. As far as I can see, I'm going to have to monitor the process rather than the service. It's now a question of how to achieve that, within my working parameters [font='Comic Sans MS']Eagles may soar high but weasels dont get sucked into jet engines[/font] Link to comment Share on other sites More sharing options...
hannes08 Posted February 29, 2012 Share Posted February 29, 2012 Hey shornm, as I said, you can query the state of a service with "sc". The service will transist from "RUNNING" over "STOPPING" to "STOPPED" (and reverse: "STOPPED" to "STARTING" to "RUNNING"). I think with this Information you can build your own "Sleep" function, right? Regards,Hannes[spoiler]If you can't convince them, confuse them![/spoiler] Link to comment Share on other sites More sharing options...
hannes08 Posted February 29, 2012 Share Posted February 29, 2012 Here's what I use: expandcollapse popup#region ;**** Directives created by AutoIt3Wrapper_GUI **** #AutoIt3Wrapper_UseUpx=n #AutoIt3Wrapper_Change2CUI=y #AutoIt3Wrapper_Res_Fileversion=1.0.0.10 #AutoIt3Wrapper_Res_FileVersion_AutoIncrement=p #AutoIt3Wrapper_Res_Language=1033 #AutoIt3Wrapper_Run_Tidy=y #endregion ;**** Directives created by AutoIt3Wrapper_GUI **** #cs ---------------------------------------------------------------------------- # # AutoIt Version: 3.3.6.0 # Author: hannes08 # # Script Function: # Checks a specified service on a specified server. If it is not running in between a specified timeout period the script will exit with an error. # # Script Parameters: # CheckService.exe <server> <service> <timeout> [<condition>] # <server> - i.e. "lifd01" or "172.19.2.200" # <service> - i.e. "snmp" or "Lotus Domino Server (DData)" # <timeout> - i.e. 300 -- value in Seconds! # [<condition>] - 0 OR 1 -- 0: Service has to be stopped to complete successfully # 1: Service has to be running to complete successfully # Default value for optional parameter <condition> is 1 ("running") # # #ce ---------------------------------------------------------------------------- #include <Constants.au3> #include <Timers.au3> ConsoleWrite("Starting (Version " & FileGetVersion(@ScriptName) & ")" & @CRLF) If $CmdLine[0] = 3 Then $s_cond = "running" ElseIf $CmdLine[0] = 4 Then If StringIsInt($CmdLine[4]) Then If $CmdLine[4] = 0 Then $s_cond = "stopped" ElseIf $CmdLine[4] = 1 Then $s_cond = "running" Else ConsoleWrite("Parameter <condition> has a wrong format." & @CRLF & "Expected: 0 or 1" & @CRLF & "Recieved: " & $CmdLine[4]) Exit 5 EndIf Else ConsoleWrite("Parameter <condition> has a wrong format." & @CRLF & "Expected: Integer: 0 or 1" & @CRLF & "Recieved: " & $CmdLine[4]) Exit 6 EndIf EndIf If StringInStr($CmdLineRaw, '""') Then ConsoleWrite("No Service specified. This could be by default." & @CRLF & "Exit" & @CRLF) Exit 0 EndIf If $CmdLine[0] = 3 Or $CmdLine[0] = 4 Then ;~ MsgBox(0,"test"," /c sc " & $CmdLine[1] & " """ & $CmdLine[2] & """ | find /C /I ""state"" >> test.cmd") If Ping($CmdLine[1]) > 0 Then ConsoleWrite("Checking for service: """ & $CmdLine[2] & """ on server: """ & $CmdLine[1] & """" & @CRLF) $t = _Timer_Init() $b_stopped = False While _Timer_Diff($t) / 1000 <= $CmdLine[3] $rc = Run(@ComSpec & " /c sc " & $CmdLine[1] & " query """ & $CmdLine[2] & """ | find /C /I """ & $s_cond & """", @ScriptDir, @SW_MINIMIZE, $STDERR_CHILD + $STDOUT_CHILD) $s_line = "" $s_rc = "" While 1 $s_line = StdoutRead($rc) If @error Then ExitLoop If StringStripWS($s_line, 3) <> "" Then $i_sec = Floor(_Timer_Diff($t) / 1000) If Mod($i_sec, 5) = 0 Then ConsoleWrite("Message after " & $i_sec & "s: " & StringStripWS($s_line, 3) & @CRLF) If StringStripWS($s_line, 3) = 1 Then $b_stopped = True ConsoleWrite("State (""" & $s_cond & """) for service " & $CmdLine[2] & " has been successfully identified after " & $i_sec & " seconds." & @CRLF) EndIf Else EndIf WEnd If $b_stopped = True Then ExitLoop Sleep(1000) WEnd If $b_stopped Then ConsoleWrite("Service is " & $s_cond & "!" & @CRLF) Exit 0 Else ConsoleWrite("State (""" & $s_cond & """) for service has not been identified after " & $CmdLine[3] & "s of waiting ... Timeout encountered." & @CRLF) Exit 4 EndIf Else ConsoleWrite("Remote machine is not available!" & @CRLF) Exit 3 EndIf ElseIf $CmdLine[0] = 0 Then ConsoleWrite("No Parameter given. This could be by default." & @CRLF & "Exit" & @CRLF) Exit 0 ElseIf $CmdLine[0] = 1 Then ConsoleWrite("No Service specified. This could be by default." & @CRLF & "Exit" & @CRLF) Exit 0 Else If StringInStr($CmdLineRaw, '""') Then ConsoleWrite("No Service specified. This could be by default." & @CRLF & "Exit" & @CRLF) Exit 0 EndIf ConsoleWrite("Wrong Parameter count." & @CRLF & "Expected: 3 or 4 (Servername, Service, Timeout [, condition])" & @CRLF & "Recieved: " & $CmdLine[0] & @CRLF) Exit 1 EndIf Regards,Hannes[spoiler]If you can't convince them, confuse them![/spoiler] Link to comment Share on other sites More sharing options...
shornw Posted February 29, 2012 Author Share Posted February 29, 2012 Hi Hannes. I have to be completely honest on two counts: 1. I wasn't aware that 'SC' reported quite so accurately. I have in the past used Net Start / Stop in .bat files but not SC. I thought it only appeared on later O/S's. I stand corrected and thank you for that 2. I was kinda hoping to have a simpler (in my mind cleaner) solution without having to split/strip and general handling of strings. My ideal would have been remote process monitoring, but I can work with this, so I'll make a start. Thanks for the pointer and the sample you posted (although that's way more complex than I need it to be for this ) [font='Comic Sans MS']Eagles may soar high but weasels dont get sucked into jet engines[/font] Link to comment Share on other sites More sharing options...
hannes08 Posted February 29, 2012 Share Posted February 29, 2012 Hey shornw, to make it easier and more proper for you: #include <Constants.au3> $pc = @ComputerName $servicename = "MyService" $s_line = "" $rc = Run(@ComSpec & " /c sc " & $pc & " query """ & $servicename & """ | find ""STATE""", @ScriptDir, @SW_MINIMIZE, $STDERR_CHILD + $STDOUT_CHILD) While 1 $s_line &= StdoutRead($rc) If @error Then ExitLoop WEnd $s_line = StringStripWS($s_line, 7) $a_temp = StringSplit($s_line, " ") If $a_temp[0] > 2 Then Switch $a_temp[3] Case 1 "Service State: STOPPED" Case 2 "Service State: START_PENDING" Case 3 "Service State: STOP_PENDING" Case 4 "Service State: RUNNING" EndSwitch EndIf Regards,Hannes[spoiler]If you can't convince them, confuse them![/spoiler] Link to comment Share on other sites More sharing options...
z0iid Posted March 14, 2012 Share Posted March 14, 2012 Or - save this as UDF: expandcollapse popup$service = "" ConsoleWrite(_SetServiceState(@ComputerName, $service, "Stop") & @LF) Sleep ( 5000 ) ConsoleWrite(_SetServiceState(@ComputerName, $service, "Start") & @LF) Func _SetServiceState($s_pc, $service, $State) Local Const $wbemFlagReturnImmediately = 0x10 Local Const $wbemFlagForwardOnly = 0x20 Local $colItems = "", $objItem, $ret_status = -1 Local $a_status[25] = ["Success", "Not supported", "Access denied", "Dependent services running", _ "Invalid service control", "Service cannot accept control", "Service not active", "Service request timeout", _ "Unknown failure", "Path not found", "Service already stopped", "Service database locked", "Service dependency deleted", _ "Service dependency failure", "Service disabled", "Service logon failed", "Service marked for deletion", "Service no thread", _ "Status circular dependency", "Status duplicate name", "Status - invalid name", "Status - invalid parameter", _ "Status - invalid service account", "Status - service exists", "Service already paused"] If Ping($s_pc) Then Local $objWMIService = ObjGet("winmgmts:" & $s_pc & "rootCIMV2") If @error Then MsgBox(16, "_SetServiceState", "ObjGet Error: winmgmts") Return EndIf $colItems = $objWMIService.ExecQuery ("SELECT * FROM Win32_Service", "WQL", _ $wbemFlagReturnImmediately + $wbemFlagForwardOnly) If @error Then MsgBox(16, "_SetServiceState", "ExecQuery Error: SELECT * FROM Win32_Service") Return EndIf If IsObj($colItems) Then For $objItem In $colItems If $objItem.Name = $service Then Select Case $State = "Boot" Or $State = "System" Or $State = "Automatic" Or $State = "Manual" Or $State = "Disabled" $ret_status = $objItem.ChangeStartMode ($State) Case $State = "Stop" $ret_status = $objItem.StopService () Case $State = "Start" $ret_status = $objItem.StartService () Case $State = "Pause" $ret_status = $objItem.PauseService () Case $State = "Resume" $ret_status = $objItem.ResumeService () Case $State = "Delete" $ret_status = $objItem.Delete () EndSelect ExitLoop EndIf Next EndIf EndIf If $ret_status <> -1 Then Return $a_status[$ret_status] Else SetError(1) Return $ret_status EndIf EndFunc ;==>_SetServiceState Then in your script, for example: _setservicestate("computer-name", "spooler", "stop") MsgBox(0,"", "Complete") The MsgBox will not pop-up until the function completes, signifying that the service has completely stopped. Link to comment Share on other sites More sharing options...
Recommended Posts
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 accountSign in
Already have an account? Sign in here.
Sign In Now