2

So recently my internet connection have been really unsatisfactory so I'm trying to gather as much data as I can about when and for how much time the outages last. I tried some "connectivity monitoring" programs but they don't work as I want them to, so I decided to make one.

I am a complete noob in batch but from googling stuff for the past hour I came up with this:

SET status="

:start_test
timeout 5
ping -n 2 -w 700 www.google.com | find "bytes="
IF %ERRORLEVEL% EQU 0 (
    SET internet=Connected to the internet.

) ELSE (
    SET internet=Not connected to the internet.
)
IF %status%==%internet%(
goto :start_test
) ELSE (
goto :teller 
)

:teller
echo ------------------------------------------
echo %internet%
@echo %time%
echo ------------------------------------------
SET status=%internet%
goto :start_test

tl;dr- it checks the internet connection by pining google.com and writes a massage every time the internet connection status changes

but the problem is that it doesn't work and I don't know why, when I try to run it the console opens, goes through the first few lines and closes itself.

Help

EDIT: it works now, this is how the file looks now (just like what Mofi said):

@echo off
SET "status="

:start_test
timeout 5
ping -n 2 -w 700 www.google.com | find "bytes="
IF %ERRORLEVEL% EQU 0 (
    SET internet=Connected to the internet.

) ELSE (
    SET internet=Not connected to the internet.
)
IF "%status%"=="%internet%" (
goto :start_test
) ELSE (
goto :teller 
)

:teller
echo ------------------------------------------
echo %internet%
@echo %time%
echo ------------------------------------------
SET "status=%internet%"
goto :start_test
AmitAM
  • 41
  • 2
  • 8
  • You need to be careful what you are checking; these checks only determine one thing, whether the machine is getting returned ping information. It doesn't tell you anything about why. Make sure that you check your router logs and router settings first. You need to change three things in the snippet you've posted, `SET status="` to `SET "status="`, `IF %status%==%internet%(` to `IF "%status%"=="%internet%" (` and `SET status=%internet%` to `SET "status=%internet%"`. – Compo May 13 '17 at 11:29
  • FYI, it appears that the changes you've made in your edited version are exactly the three changes I gave you in my comment. For that reason **it's a little unfair to credit that to Mofi**. – Compo May 13 '17 at 12:15

1 Answers1

1

The answer on batch file comparison of variable with constant fails explains in first chapter how to debug a batch file by not double clicking on it, but by opening a command prompt window and running the batch file from within this window to see error messages caused by syntax errors which result in exiting batch file execution.


SET status="

This line defines the environment variable status with the value ".

I suppose you wanted to use:

SET "status="

This line deletes a perhaps existing environment variable status, but you coded this wrong by omitting the first double quote.


The command PING sets ERRORLEVEL to 0 on success and 1 on an error like target could not be pinged.

But for some unknown reason you don't want to evaluate the exit code of PING and instead parse output of PING by FIND and evaluate the exit code of FIND.

The usage of FIND is in my point of view completely unnecessary here.


The evaluation of the exit code of FIND would be already enough to continue depending on this exit code, but two different strings with spaces are assigned to an environment variable depending on value of ERRORLEVEL.


One more IF is used to branch depending more or less on exit code of PING.

Here is your mistake causing exiting batch execution because of a syntax error.

IF %status%==%internet%(

expands on first comparison to

IF " == Connected to the internet. (

or to

IF " == Not connected to the internet. (

Both lines can't be correct processed by Windows command interpreter indicated by a syntax error message output to console which can be read when the batch file is executed from within a command prompt window.

Comparing strings containing command separator character SPACE requires enclosing both strings to compare in double quotes, i.e. use:

IF "%status%" == "%internet%" (

But even this would not help here because of environment variable status is defined with a single double quote which results in left string being finally on first comparison """ which results again in a syntax error.

Note: The double quote characters are included in the string comparison.


The block below is also interesting:

IF %status%==%internet%(
goto :start_test
) ELSE (
goto :teller 
)

:teller

The ELSE branch is for jumping to the lines which would be executed in any case if the ELSE branch would not exist at all. So the complete ELSE branch is completely unnecessary.


For all the reasons above, I suggest to simplify the batch code to:

@echo off
set "Status=2"
:ConnectionTest
%SystemRoot%\System32\ping.exe -n 2 -w 700 www.google.com >nul
if errorlevel 1 (
    if not "%Status%" == "1" echo %TIME%  Not connected to the internet.
    set "Status=1"
) else (
    if not "%Status%" == "0" echo %TIME%  Connected to the internet.
    set "Status=0"
)
%SystemRoot%\System32\timeout.exe /T 5 >nul
goto ConnectionTest

It would be possible here to omit all double quotes and use:

@echo off
set Status=2
:ConnectionTest
%SystemRoot%\System32\ping.exe -n 2 -w 700 www.google.com >nul
if errorlevel 1 (
    if not %Status% == 1 echo %TIME%  Not connected to the internet.
    set Status=1
) else (
    if not %Status% == 0 echo %TIME%  Connected to the internet.
    set Status=0
)
%SystemRoot%\System32\timeout.exe /T 5 >nul
goto ConnectionTest

For understanding the used commands and how they work, open a command prompt window, execute there the following commands, and read entirely all help pages displayed for each command very carefully.

  • echo /?
  • goto /?
  • if /?
  • ping /?
  • set /?
  • timeout /?

Read also the Microsoft article about using command redirection operators.

Mofi
  • 46,139
  • 17
  • 80
  • 143
  • try `ping `, where `` is a nonexistent address in your network. `ping` will come up with `Reply from : destination not reachable` and consequently with an errorlevel of zero (Success). (Yes, it's unlikely that `www.google.com` will be in the local network, but) that's why `find` is (generally) the safer way. – Stephan Jan 06 '19 at 18:10
  • @Stephan Thanks for this add-on. But there would be even more add-ons necessary to explain all possible variants on which a ping of a different device using IP address or host name fails and exit code of `ping` is nevertheless `0`. I don't like the usage of `find "bytes="` because it is language dependent. For example on German Windows XP it is necessary to use at least `find /I "bytes="` because output text is in German and contains on successful `ping` the string `Bytes=`, but not `bytes=`. I don't know what is output by `ping` in other languages than German and English. – Mofi Jan 06 '19 at 18:35
  • @Stephan There is also no guarantee that output always contains case-insensitive the string `bytes=` on successful `ping`. For example on English Windows 7 the output of `ping localhost -n 1` does not contain `bytes=` (with no connection to any network) although the ping is successful. `ping localhost -n 1` on German Windows XP contains `Bytes=`. These are the reasons why I don't like it in general to evaluate the output text of a command which is language and version dependent in a batch file which should work on any Windows PC. – Mofi Jan 06 '19 at 18:41
  • `TTL` is language independent. Or as someone pointet out some years ago `TTL=` is the most secure search string (as `TTL` could be part of a hostname, but `=` can't). So instead of `ping` errorlevel or something like `...|find "Reply"`, use `ping ...|find "TTL="`. Until now I found no hint to a failure of this approach. – Stephan Jan 06 '19 at 19:14
  • @Stephan `| find "TTL="` could be indeed most useful approach for __IPv4__ addresses. Interesting is `ping localhost -n 1` results in ping of `::1:` (IPv6 address) on my English Windows 7 on which output does not contain `bytes=` and also not `TTL=`. But the output contains `bytes=` and `TTL=` on using `ping 127.0.0.1 -n 1` to ping `localhost` explicitly with IPv4 address. It looks like the ping output between the line with `Pinging ...` and the line `Ping statistics for ...` depends also on using IPv4 or IPv6. A real general `ping` results evaluation is really difficult. – Mofi Jan 06 '19 at 19:43
  • yes, I agree. They completely changed the output for IPv6. Above is valid only for IPv4 (`ping -4`). – Stephan Jan 06 '19 at 20:55