0

Here is what I've been using:

PING -n 1 10.0.0.1|find "Reply from" >NUL
IF NOT ERRORLEVEL 1 goto :PASS
IF     ERRORLEVEL 1 goto :FAIL

But this only works if the IP matches.

So, I found these commands on this site (in an answer by Wernfried Domscheit) that seem to work on their own but I don't know how to incorporate them together:

In a Batch file:

for /f "tokens=2 delims=:" %%g in ('netsh interface ip show address ^| findstr "Default Gateway"') do ping %%g

At the cmd prompt:

for /f "tokens=2 delims=:" %g in ('netsh interface ip show address ^| findstr "Default Gateway"') do ping %g

Any advice?

nobody
  • 19,814
  • 17
  • 56
  • 77
John Houk
  • 5
  • 3
  • 1
    `findstr /I /C:"Default Gateway"` – JosefZ Jan 14 '17 at 00:52
  • `for /F "tokens=2 delims=: " %%G in ('netsh interface ip show address ^| find "Default Gateway"') do ping %%G | find "Reply from" > nul` – aschipfl Jan 14 '17 at 01:56
  • 1
    The FOR syntax must be different in batch (double `%%`) vs, command line (single `%`) - That difference is an inherent design feature of cmd.exe. But what are you actually trying to do? What do you mean by *"this only works if the ip matches"*?. We can't give advice if you don't clearly explain your problem. – dbenham Jan 14 '17 at 14:44

2 Answers2

0

Instead of checking if the ping output contains "Reply from", it's better to search for "TTL=":

ping -n 1 10.0.0.1| findstr "TTL="

as pointed in this answer. Searching for "TTL=" after a ping will be more reliable than searching for "Reply from". There are some ping error messages with "Reply from". In some cases you can get a reply from another machine stating that the machine you're looking for is not reachable for example. You'll then have a "Reply from" in the failed ping output.

If you want to use the ping with the findstr and its errorlevel in a for loop you cannot not use goto to jump to a label. The goto will destroy your loop context. You can see goto as a command that tells the parser to abandon the command it was processing/executing (the FOR loop) and start at the label you gave as argument. It will just forget about the loop.

I will assume your labels are arranged this way:

:PASS
rem some commands in case the ping succeeded
<commands_succes>
goto :BOTH

:FAIL
rem some code in case the ping failed
<commands_fail>

:BOTH
rem code that has to be executed in both cases after code for individual case (if any)
<commands_after>

Your loop can then take these different forms:

  • using IF ERRORLEVEL 1 ( ... ) ELSE ( ) and move all code from the :FAIL label to the if-branch and all code from the :PASS label to the else-branch. The code from the :BOTH label (if any) will come under the whole if-block

    for /f "tokens=2 delims=:" %%g in ('netsh interface ip show address ^| findstr /C:"Default Gateway"') do (
        ping %%g | findstr "TTL=">NUL
        IF ERRORLEVEL 1 (
            rem Here comes code in case the ping failed (code for :FAIL label)
            <commands_fail>
        ) ELSE (
            rem Here comes code in case the ping succeeded (code for :PASS label)
            <commands_succes>
        )
        rem code that has to be executed in both cases after code for individual case (if any)
        <commands_after>
    )
    
  • use function calls with the call command instead of goto. If the call command is used with labels it does the same as the goto except that the parser will remember its state (command it was executing) and will come back to it after the execution of the label is exited. so it will execute commands from the label untill an explicit exit, goto :EOF or end of file is encountered.

    for /f "tokens=2 delims=:" %%g in ('netsh interface ip show address ^| findstr /C:"Default Gateway"') do (
        ping %%g | findstr "TTL=" > NUL
        IF ERRORLEVEL 1 (
            rem ping failed
            call :FAIL
        ) ELSE (
            rem ping succeeded
            call :PASS
        )
    )
    
    exit /b 0
    
    :PASS
    rem some commands in case the ping succeeded
    <commands_succes>
    goto :BOTH
    
    :FAIL
    rem some code in case the ping failed
    <commands_fail>
    
    :BOTH
    rem code that has to be executed in both cases after code for individual case (if any)
    <commands_after>
    exit /b 0
    

Both cases should work for you. You'll just have to copy-paste the code corresponding to the <commands_fail>, <commands_success> and <commands_after> on the right places. If you don't have anything in <commands_after> you can just leave it blank.

EDIT: Thanks to @Josefz who noticed a little mistake I missed in the command you use in the FOR loops to get the IP address of the default gateway:

netsh interface ip show address | findstr "Default Gateway"

The issue is that findstr uses whitespace as delimiter for its regular expressions (whitespace in findstr = | in grep = OR operator). So what it will be looking for in the case above is Default or Gateway and will not only give you the default gateway but also the gateway metric which isn't even an IP address. Use the /C switch of findstr to make it look for litteral string Default Gateway:

netsh interface ip show address | findstr /C:"Default Gateway"

I've corrected it in the code samples above as well.

Good luck!

PS: In both cases you can use conditional execution instead of checking the errorlevel. Follow the link for more info but be sure to read the note also!

Community
  • 1
  • 1
J.Baoby
  • 2,167
  • 2
  • 11
  • 17
  • 1
    You can't omit `/C:` qualification in `findstr /C:"Default Gateway"` (Uses specified string as a **literal search string**). Otherwise a match found in `Default Gateway` as well as `Gateway Metric` property name; the latter in **un`ping`able**. – JosefZ Jan 14 '17 at 13:24
  • @JosefZ that's completely true. I missed that little mistake from the OP. Thanks for pointing that out. I'll edit my answer right away – J.Baoby Jan 14 '17 at 13:28
0

Although not clearly stated, i'll assume that you want to use the IP found by your second command in the first one. That's simply:

for /f "tokens=2 delims=:" %%g in ('netsh interface ip show address ^| findstr "Default Gateway"') do SET IP=%%g
PING -n 1 %IP%|find "Reply from" >NUL
IF NOT ERRORLEVEL 1 goto :PASS
IF     ERRORLEVEL 1 goto :FAIL

You set a variable (IP) in the for statement, and use it instead of the fixed ip in the ping.

ths
  • 2,858
  • 1
  • 16
  • 21