I want to stop and start a Windows service from a remote PC using the Windows command line, in a batch file.

sc \\ stop <ServiceName>

rem sc \\ query <ServiceName> | findstr STATUS | SET VAR=

However, I want to wait until the status of the service is assured to be stopped or started. So I was planning to loop and check the status continuously until the status is STOPPED.

I think that repeated request to the server may be processor intensive but there is no wait for the command line except for some hacks on checking time. But my main question is how do I get the status of the Windows service so I can check with an IF statement if it is OK to proceed to the next command?


To set a variable to the output of a command, use for /f:

for /f "tokens=*" %%a in ('command') do set _CmdResult=%%a

The problem is, to use a pipe in the command you need to escape it with the command line escape character: ^, therefore: ^|.

for /f "tokens=*" %%a in ('sc \\ query <ServiceName> ^| findstr STATUS') do set _CmdResult=%%a

Now, I'm not sure which version of Windows you're running, but my attempts at a sc query on Windows 7 give the following output:

>sc query SamSs
        TYPE               : 20  WIN32_SHARE_PROCESS
        STATE              : 4  RUNNING
                                (NOT_STOPPABLE, NOT_PAUSABLE, IGNORES_SHUTDOWN)
        WIN32_EXIT_CODE    : 0  (0x0)
        SERVICE_EXIT_CODE  : 0  (0x0)
        CHECKPOINT         : 0x0
        WAIT_HINT          : 0x0

This means a findstr STATE would be required, which gives the output:

>sc query SamSs | findstr STATE
        STATE              : 4  RUNNING

Now, in the example above, tokens=* means every token is set to the variable %%a, where tokens are separated by spaces. In this case, you can use either the third token (4) or fourth token (RUNNING). By the way, with testing, 1 corresponds to STOPPED for me.

To make things easier, I'll be using the string RUNNING in this example. So we want the fourth token.

for /f "tokens=4" %%a in ('sc \\ query <ServiceName> ^| findstr STATE') do set _CmdResult=%%a

Of course, depending on what your sc query outputs, yours may be slightly different, so follow how I got there and modify as needed. Or post in a comment the output of your sc query and I'll modify as needed.

To check the value, you can use:

if %_CmdResult%==STOPPED (
    REM do something here

In your case, the loop would go something like this.

for /f "tokens=*" %%a in ('sc \\ query <ServiceName> ^| findstr STATUS') do set _CmdResult=%%a
if %_CmdResult%==STOPPED (
    sc \\ start <ServiceName>
    goto endloop
timeout /t 5
goto loop

Note that timeout is a utility only included in Windows Vista and later. Windows XP can use something like ping -n 1 -w 5000 > nul.

  • Thanks Bob, It was very detailed. But I guess the tiny bit that was missing in my code was the escaped pipe using the caret character. But this would be helpful for future reference. :)
    – Nassign
    Mar 28 '12 at 9:29
  • 1
    Thanks for ^| I was getting | was unexpected at this time. without it.
    – Nae
    Feb 26 '19 at 8:38
  • thank you so much for the ^| !!
    – Smock
    Jun 19 '19 at 14:10
  • I don't understand how the tokens=* and tokens=4 parameter works - can you explain it?
    – Dai
    Mar 4 at 8:09
  • @Dai It's a bit much to explain in comments, but the for /? help text is quite descriptive, and this website has rather detailed descriptions. If you need further explanation, asking a new question might be useful. In short, tokens=4 gets you the 4th space-delimited field from the command output. tokens=* gets you the entire line.
    – Bob
    Mar 4 at 16:22

A More advanced example with higher complexity level

(but also higher usability)

  • using several common application (cURL, GREP, SED) you can either download a Win32 pre-build versions of those or use cygwin's exe files in Windows- both works perfectly fine (for cygwin, better just put c:\cygwin\bin\ folder location in your system's PATH variable for easier access).
  • PIPE processing (STDOUT and STDERR are processed through).
  • escaped symbols (|, >, &) - best practice / required on Windows7+.
  • no loops, no goto
  • working with numeric data (curl's response header Content-Length)

@echo off

setlocal enableextensions
  for /f "tokens=*" %%a in ('curl --head --ipv4 --sslv3 --silent --location-trusted --url "https://storage.googleapis.com/chromium-browser-continuous/Win_x64/362418/mini_installer.exe" 2^>^&1 ^| grep "Content-Length" 2^>^&1 ^| sed "s/\r\n$//g" 2^>^&1 ^| sed "s/content-length\:\ //gi" 2^>^&1') do ( set /a num=%%a )

  set /a num=%num% / 1024 / 1024

  echo it is %num%MB

will output it is 41MB

(original header is Content-Length: 43597312)

took it from here: - CMD/Bash Script Ninja - cURL Response Header Number Manipulation


You may want to check PsTools by Microsoft (Sysinternals). There is an tool called PsService where you can remotely check the services via the parameter \\computer


it's just an exemple to know how can "set yyy" out "yyy=1 toto" the first une ( ) out "yyy=1 toto" but the line juste after say "Environment variable yyy not defined"

echo toto tata titi|awk.exe -F"tata" "{print NR,$1}"|(set /p yyy=&set yyy)
set yyy
  • 1
    I don't understand how this answers the question. You seem to be answering a different question.
    – Chenmunka
    Aug 29 '17 at 10:43
  • sorry i am not good in english loll ... when i do : echo toto tata titi|awk.exe -F"tata" "{print NR,$1}"|(set /p yyy=&set yyy) the set yyy at the end of line print : yyy=1 toto the set yyy at the second line print : Environment variable yyy not defined how can change the first line of the code for that set yyy of seconde line print : yyy=1 toto
    – Risoos
    Aug 31 '17 at 4:33

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.