SC Query output

Posted on 2012-09-20
Last Modified: 2014-06-13

Could someone please enlighten me as to how do the following.
From time to time I need to shut down an application that runs as a service on a large number of servers, the service that requires shutting down can take anything from 30-60 mins and following a successful shutdown I need to run a súpplíed batch file that will that will run updates against this application.
Where I am stuck is on how to get a batch file to pick up on sc query "state stopped" on each server and if the service has stopped for the batch file to kick in.

So I am assuming the simplified order of this is.

1.Shutdown Service
2.Run sc query
3.If state stopped then run supplied_update.bat
4.If not wait or check again in 30 mins etc

Many Thanks
Question by:steveuk71
    LVL 51

    Assisted Solution

    by:Bill Prew
    It's pretty easy to check the state of a service remotely, and stop or start it as needed, that can be done easy enough.

    The bigger problem you are going to have I think is keeping track of which servers have been done, and which haven't.  You will want to loop through a file that lists each server name, and then process that server.  But I don't think you want to wait 30 to 60 minutes on each server for the service to stop, before going to the next server.

    Rather I would think you would start with a list of servers to be processed, and loop over them.  For any that the service is running, initiate a stop of the service, and then move on to the next server.  For any servers where the service is already stopped, perform the update, and restart.

    Then you need to keep rechecking the servers that you initiated the stop on, maybe every 5 minutes, to see when the service is stopped, so you can perform the update.  For every server updated, you remove it from the list.

    Hope that makes a little sense, we could come up with a way to do this, but wanted to say it out loud before I did any scripting to make sure you agreed.

    LVL 37

    Expert Comment

    by:Gerwin Jansen
    The sc query command could look like this:
    sc \\ServerName ServiceName | findstr /i "stopped"

    Open in new window

    After the sc command, check %ERRORLEVEL% to determine whether the service was stopped, 0 would mean is has stopped, 1 would mean that it has another state. You could also explicitly check for "running" before you attempt the sc stop command.

    I agree with Bill on using a servername list, you could add a status file per server to keep track of the service's state on each server.

    Author Comment

    Thanks Bill and Gerwin, Bill I agree with your comment and if there is any chance of some assistance with this matter it would be most appreciated.
    Gerwin,the status file per server sounds interesting, could you please elaborate if possible.
    LVL 82

    Accepted Solution

    For the fun of it; you might want to change the properties of your cmd console to be wider than 80 characters. The script will spawn a separate cmd window for each server in the list that will do the actual updating; the main script window will only monitor the progress (closing/killing the main window will NOT close the spawned windows!). You can add your own code where indicated, starting in line 181.
    The script requires sleep.exe from the W2k3 Resource Kit (; put it somewhere in the path or in the script's folder.
    @echo off
    setlocal enabledelayedexpansion
    REM *** (Path and) name of the file with the server list to process (one name per line, no leading backslashes; host names, FQDN, or IP.
    set ServerList=%~dp0ServerList.txt
    REM *** Name of the service to stop/start:
    set Service=Some Service
    REM *** Timeout for service stop/start in minutes:
    set TimeoutServiceStop=240
    set TimeoutServiceStart=120
    REM *** Monitor refresh interval in seconds:
    set RefreshInterval=5
    REM *** Service poll interval in seconds:
    set QueryInterval=10
    REM *** Time for the spawned windows to remain open once the server has been processed:
    set DisplayDelay=10
    REM *** Column headers:
    set Col1Name=Computer
    set Col2Name=Time
    set Col3Name=Status
    set Col4Name=Message
    REM ***  Column sizes (13 more characters are required for the table lines):
    set Col1Size=20
    set Col2Size=13
    set Col3Size=6
    set Col4Size=80
    set echo2=^<NUL set /p Dummy=
    (set FillerSpace=                                                                                                    )
    (set FillerLine=----------------------------------------------------------------------------------------------------)
    set StatusFolder=%~dp0Status
    if /i "%~1"=="/spawn" (goto :Process)
    if not exist "%StatusFolder%" md "%StatusFolder%"
    set /a i = 0
    for /f "usebackq" %%a in ("%ServerList%") do (
    	echo Creating status file for %%~a ...
    	call :SetStatus "%%~a" "BUSY" "Waiting for start."
    	set /a i += 1
    	set Server[!i!]=%%~a
    set /a ServerCount = i
    for /l %%i in (1, 1, %ServerCount%) do (
    	echo Spawning process for !Server[%%i]! ...
    	start "" /min "%~f0" /spawn !Server[%%i]!
    	sleep.exe -m 500
    call :FormatString Col1Name %Col1Size% FillerSpace
    call :FormatString Col2Name %Col2Size% FillerSpace
    call :FormatString Col3Name %Col3Size% FillerSpace
    call :FormatString Col4Name %Col4Size% FillerSpace
    set Header=^^^| %Col1Name% ^^^| %Col2Name% ^^^| %Col3Name% ^^^| %Col4Name% ^^^|
    set HLine=+-!FillerLine:~0,%Col1Size%!-+-!FillerLine:~0,%Col2Size%!-+-!FillerLine:~0,%Col3Size%!-+-!FillerLine:~0,%Col4Size%!-+
    	echo %HLine%
    	echo %Header%
    	echo %HLine%
    	set Done=1
    	for /l %%i in (1, 1, %ServerCount%) do (
    		set Server=!Server[%%i]!
    		call :GetStatus !Server! StatusTime Status Message
    		if "!Status!" equ "BUSY" (set Done=0)
    		call :FormatString Server %Col1Size% FillerSpace
    		call :FormatString StatusTime %Col2Size% FillerSpace
    		call :FormatString Status %Col3Size% FillerSpace
    		call :FormatString Message %Col4Size% FillerSpace
    		set Line[%%i]=^^^| !Server! ^^^| !StatusTime! ^^^| !Status! ^^^| !Message! ^^^|
    	for /l %%i in (1, 1, %ServerCount%) do (
    		echo !Line[%%i]!
    	echo %HLine%
    	sleep %RefreshInterval%
    if "%Done%" equ "0" goto LoopMonitor
    echo Done.
    set /a SuccessCount = 0
    set /a ErrorCount = 0
    for /l %%i in (1, 1, %ServerCount%) do (
    	call :GetStatus !Server[%%i]! StatusTime Status Message
    	if "!Status!" equ "OK" (
    		set /a SuccessCount += 1
    	) else (
    		set /a ErrorCount += 1
    echo Successfully updated %SuccessCount% machines, errors on %ErrorCount% machines.
    goto :eof
    REM ********************************************************************************
    REM *** Helper function
    >"%StatusFolder%\%~1.ini" echo "%Time%"~"%~2"~"%~3"
    goto :eof
    for /f "usebackq tokens=1-3 delims=~" %%a in ("%StatusFolder%\%~1!.ini") do (
    	set %2=%%~a
    	set %3=%%~b
    	set %4=%%~c
    goto :eof
    set _tmp_=!%1!!%3!
    set %1=!_tmp_:~0,%2!
    set Server=%~1
    set Action=%~2
    if /i "%Action%"=="stop" (
    	set TimeoutService=%TimeoutServiceStop%
    	set QueryString=STOPPED
    ) else (
    	set TimeoutService=%TimeoutServiceStart%
    	set QueryString=RUNNING
    set /a Timeout = 60 * TimeoutService / QueryInterval
    sc.exe \\%Server% %Action% "%Service%" >NUL 2>&1
    if %errorlevel% equ 1062 (
    	call :SetStatus %Server% "BUSY" "Service Control '%Action%': already stopped."
    	exit /b 0
    if %errorlevel% neq 0 (
    	call :SetStatus %Server% "ERROR" "Service Control: could not send %Action% signal; errorlevel: %errorlevel%"
    	exit /b 1
    set /a CurrentWait = 0
    %echo2% [%Time%] Waiting for state '%QueryString%' ^(Timeout %TimeoutService% minutes^)
    	sleep.exe %QueryInterval%
    	set /a CurrentWait += QueryInterval
    	set QueryState=INACCESSIBLE
    	for /f "tokens=1* delims=: " %%a in ('sc.exe \\%Server% query "%Service%" 2^>NUL') do (
    		if "%%a" equ "STATE" (set QueryState=%%b)
    	if "%QueryState%" neq "!QueryState:%QueryString%=!" (
    		call :SetStatus %Server% "BUSY" "Service Control '%Action%': success."
    		echo.& exit /b 0
    	if "%QueryState%" equ "INACCESSIBLE" (
    		call :SetStatus %Server% "ERROR" "Service Control '%Action%': lost access to remote SCM; last state: %QueryState%"
    		echo.& exit /b 1
    	If %CurrentWait% geq %Timeout% (
    		call :SetStatus %Server% "ERROR" "Service Control '%Action%': timeout of %TimeoutService% minutes reached; last state: %QueryState%"
    		echo.& exit /b 1
    	call :SetStatus %Server% "BUSY" "Service Control '%Action%': waiting for state '%QueryString%'; current state: %QueryState%"
    goto LoopQuery
    REM ********************************************************************************
    REM *** Spawned processing of a server
    set Server=%~2
    title %~n0 - %Server%
    call :SetStatus %Server% "BUSY" "Pinging"
    echo [%Time%] Pinging %Server% ...
    ping.exe %Server% | find /i "TTL" >NUL
    if errorlevel 1 (
    	call :SetStatus %Server% "ERROR" "No response to ping."
    	echo ... no response; leaving.
    	goto Leave
    echo [%Time%] Stopping service ...
    call :SetStatus %Server% "BUSY" "Stopping service"
    call :ServiceControl %Server% stop
    if errorlevel 1 (goto Leave)
    echo [%Time%] Running Update ...
    call :SetStatus %Server% "BUSY" "Updating"
    REM *** Update the server here; replace "SLEEP 15" with whatever you need to do, for example 'call supplied_update.bat %Server%'
    SLEEP 15
    echo [%Time%] Starting service ...
    call :SetStatus %Server% "BUSY" "Starting service"
    call :ServiceControl %Server% start
    if errorlevel 1 (goto Leave)
    echo [%Time%] Done.
    call :SetStatus %Server% "OK" "Successfully updated."
    sleep.exe %DisplayDelay%

    Open in new window


    Author Comment

    Many Many Thanks for this assistance, I haven't had time to go through and attempt to understand it just yet.

    Featured Post

    Do email signature updates give you a headache?

    Constantly trying to correctly format email signatures? Spending all of your time at every user’s desk to make updates? Want high-quality HTML signatures on all devices, including on mobiles and Macs? Then, let Exclaimer solve all your email signature problems today!

    Join & Write a Comment

    I've always wanted to allow a user to have a printer no matter where they login. The steps below will show you how to achieve just that. In this Article I'll show how to deploy printers automatically with group policy and then using security fil…
    Have you considered what group policies are backwards and forwards compatible? Windows Active Directory servers and clients use group policy templates to deploy sets of policies within your domain. But, there is a catch to deploying policies. The…
    This video discusses moving either the default database or any database to a new volume.
    In this tutorial you'll learn about bandwidth monitoring with flows and packet sniffing with our network monitoring solution PRTG Network Monitor ( If you're interested in additional methods for monitoring bandwidt…

    730 members asked questions and received personalized solutions in the past 7 days.

    Join the community of 500,000 technology professionals and ask your questions.

    Join & Ask a Question

    Need Help in Real-Time?

    Connect with top rated Experts

    17 Experts available now in Live!

    Get 1:1 Help Now