2

Looking to use findstr to get it to find "0% loss" after a ping command. Perhaps an array of anything up to "50% loss".

This is for checking and ensuring a connection to the internet is 100% established before launching something online.

Currently it's structured:

ping %ip% -n 3 -w 3000 | findstr "0% loss"
pause
goto Starting

It's currently ignoring findstr and no matter what it refuses to find what I'm looking for

Ideally it would flow like:

ping %ip% -n 3 -w 3000 | findstr "0% loss" || goto Echo
pause
goto Starting
:echo
Could not find "0% loss"
pause

And I have tried that, it will go to echo, but even with 100% connection so it's clearly just not operating how I'd like it to.

Is there a better way to find % packet loss?

Or

Is there a better way to test internet connection, given ping doesn't work when a device is totally offline.

Cinn
  • 71
  • 1
  • 11
  • What is it showing for you? What you have works fine for me. – SomethingDark Jul 23 '17 at 01:43
  • @SomethingDark for me it's not discerning anything `@echo off title Restart color 0A cls :start Cls set ip=www.google.com :Pingcheck echo Checking ping.. timeout /t 3 ping %ip% -n 5 -w 3000 | findstr "0% loss" || goto Loss pause :Echo echo We found 0 packet loss, at %ip% on %date% at %time% pause goto start :Loss echo We found some packet loss. pause` it will run and report 0% packetloss regardless of what the **actual** internet state is. – Cinn Jul 23 '17 at 02:45
  • @Cinn: Why don't you extract `Sent` and `Received` packets and calculate the percent loss yourself? – Azeem Jul 23 '17 at 03:45
  • 1
    @Azeem - batch doesn't play nice with non-integers – SomethingDark Jul 23 '17 at 03:46
  • Your problem stems from the fact that "0% loss" is also the last 7 characters in "100% loss" – SomethingDark Jul 23 '17 at 03:48

2 Answers2

4

The search string you are looking for is too broad. When you check findstr for "0% loss", you are inadvertently picking up "100% loss" as well. Fortunately, ping puts the packet loss in parentheses, so you can simply include the open parenthesis in the search string.

@echo off
title Restart
color 0A
cls

:start
Cls
set ip=www.google.com

:Pingcheck
echo Checking ping..
timeout /t 3
ping %ip% -n 5 -w 3000 | findstr /C:"(0% loss" || goto Loss
pause

:NoLoss
echo We found 0 packet loss, at %ip% on %date% at %time%
pause
goto start

:Loss
echo We found some packet loss.
pause

I've also changed the name of the :Echo label because echo is already a command and having it also be a label would be confusing.

SomethingDark
  • 13,229
  • 5
  • 50
  • 55
  • This doesn't appear to ping anything. In fact it seems it's skipping the ping all together and going straight to `:loss` – Cinn Jul 23 '17 at 04:12
  • It's piping the output of `ping` to findstr, which is then **only** displaying lines that contain the string `(0% loss`. Because `ping www.google.com` uses IPV6 by default and that doesn't work for some reason, no part of the ping command matches the search string so nothing is getting displayed. The script is working exactly how it's supposed to, because that's how `findstr` works and you said _nothing_ about needing to see the output of ping. – SomethingDark Jul 23 '17 at 04:21
  • this makes more sense. I assume it will carry out it's purpose correctly with the `| findstr /C:"(0% loss" ` added? Remembering the whole point of this is to recognize a connection to the outside web and start a program based on that being true. – Cinn Jul 23 '17 at 05:52
2

You can also check ping status with wmi. The advantage to this method is that it'll goto :fail on the first failure, and not continue its lost cause of completing 5 ping attempts, while also providing a simple way to preserve the average response time. It uses set /a to check whether the result of the wmi query contains a numeric value. If it does, pass. If not, fail.

@echo off & setlocal

set "host=www.google.com"

echo Pinging %host%...

for /L %%I in (1,1,5) do (
    for /f "delims=" %%x in (
        'wmic path win32_pingstatus where "address='%host%' and timeout=3000"^
        get ResponseTime /value ^| find "="'
    ) do (
        2>NUL set /a "%%x, avg += ResponseTime" || goto fail
    )
)

set /a "avg /= 5"
echo 0%% packet loss.  Woo.  Average response time was %avg%ms.
exit /b

:fail
echo Aw snap.  Packet loss.
rojo
  • 24,000
  • 5
  • 55
  • 101
  • Unfortunately it doesn't permit reading the `echo 0%% packet loss. Woo. Average response time was %avg%ms.` it simply closes the file if there's no PL or even if there is PL. This is set to work in conjunction with: `:Starting Echo Connection Established... Starting server Start Server.bat Echo Start Successful goto start` Is there a way to trigger the above code^ with what you posted? – Cinn Jul 23 '17 at 07:08
  • @Cinn Yeah, just insert that immediately above `exit /b`. If you're launching this script by double-clicking and want to read the results, insert a `pause` above `exit /b` and again as the the last line of the script. – rojo Jul 23 '17 at 18:34
  • This is great, it's way more advanced that what I'm used to. What I'm trying to do here is have it loop to the top, run through again, and repeat the process until it finds a stable connection. Once it does, it will `goto :Starting` and launch a server, then repeat the whole ping process again 24/7 if it must. (which is why it's critical it's 100% connection BEFORE launching the server). https://i.gyazo.com/5031f1f297033350a8fac99f0ba60fa2.png – Cinn Jul 23 '17 at 20:05
  • That code looks fine for syntax (except remove the `pause` commands for production). Also consider using `call server.bat` instead of `start server.bat`. But the logic seems off. Do you intend to call server.bat on every loop iteration, even if the service is already running? There's no check to see whether the service needs started. Use something like `wmic /node:servername /user:adminuser /password:adminpass service where "name='servicename'" get started 2>NUL | find /i "false" >NUL && call server.bat`, assuming the service is installed as a Windows service. You should post a new question. – rojo Jul 24 '17 at 13:50
  • I've tried the `call` for `server.bat` but it retorted it couldn't find server.bat, so I used start instead and put the Starter batch in the same folder. what this is for: It's a small game and the developers haven't got a proper launcher yet, it's just a batch file that calls the game.exe in -batchmode -nographics. The biggest issue is actually making it find the string "100% loss" or any kind of loss significant enough to pull the server from online. The secondary issue is having it start based on that loss AND continue monitoring until it goes down again – Cinn Jul 25 '17 at 04:18
  • Also you mentioned the calling on every iteration, this is the final problem, because the `server.bat` doesn't close on connection loss, the process continues, albeit non-functioning. So I was hoping to throw in parameters to close any currently existing iterations of the process before starting another - haven't got passed the initial problem as yet. 1. ping google ensure connection. 2. if connection - continue pinging infrequently. 3.if lost connection - ping until connection established 4. if connection established start close existing process `start server.bat` – Cinn Jul 25 '17 at 04:21