0

I'm currently running a set of commands that utilizes the timeout function in my batch files. The timeout function uses a variable for how many seconds it should pause, and I think that may be causing issues, but I desperately need it to function properly.


I've got an update to my question which details more about what may be happening.

I used some suggestions that I had in the comments to try and fix my script, but it did not work.

Here is my script:

:connectToTheInternet
    setlocal EnableDelayedExpansion 
    set timeout=2
    echo checking internet connection
    echo.
    :connectToTheInternetRestart
    ping -n 1 google.com | find /i "TTL=" >NUL && (
        echo Internet connection already established, checking script versions.
        echo.
        goto scriptVersion
        REM toupd
    ) || ( 

        if "%COUNTER%"=="0" (
            echo Creating wifi profile.
            echo.
            set /A COUNTER=1
            goto createWifiProfile
        )

        SET /A "tries = (%COUNTER%-1)+1"

        REM if failed endonfail times, give up
        if "%COUNTER%"=="%endonfail%" (
            echo Error: Could not connect to network %tries% times, stopping script.
            echo.
            goto endNoShutdown
        )

        echo.
        echo Attempt #%COUNTER%.
        echo.       
        REM raise waiting time between connections        
        SET /A "modulo = (%COUNTER%-1) %% 2"

        if "%modulo%" EQU "0" ( 
            set /A timeout=timeout+2
            echo failed %tries% times in a row. Increasing wait time between actions to %timeout% seconds.
            set /A COUNTER=COUNTER+1
        ) else ( 
            set /A COUNTER=COUNTER+1
        )

        REM disconnect existing network
        netsh wlan disconnect
        netsh wlan delete profile name="%wifissid%"

        timeout /t 1 /nobreak

        echo.
        REM attempt connection
        netsh wlan add profile filename="connect.xml"
        netsh wlan connect name="%wifissid%" ssid="%wifissid%" >NUL
        echo.
        echo Wait time is currently !timeout! seconds.
        timeout /t !timeout! /nobreak
        echo.

        REM check pings
        ping -n 1 google.com | find /i "TTL=" >NUL && (
            echo Successfully connected. Checking script version.
            echo.
            goto scriptVersion
        ) || ( 
            set /a COUNTER2=COUNTER+1
            echo Connection attempt failed. Starting attempt #%COUNTER2% in 3 seconds.
            echo.
            timeout /t 3 /nobreak
            cls
            goto connectToTheInternetRestart
        )
    )

My problem is specifically the timeout /t !timeout! /nobreak which should wait for a variabled amount of time. The problem is, sometimes (it only happens when the device successfully connects to the internet, but not every time the device connects to the internet) the timeout jumps up to 10,000 seconds, 30,000 seconds or some other random high number (And they really are random, I've seen some at like 12,536 seconds.) When it should always be less than 12 based on the timeout variable. Yes, I mean seconds NOT milliseconds. As you can imagine, there is a big difference between 10k seconds (roughly 21 days) vs 10 seconds.

I have no idea what could be causing this, or how to solve it and would love some help.

GrumpyCrouton
  • 8,486
  • 7
  • 32
  • 71
  • @robert No, I mean seconds. That's the problem - if it were milliseconds I wouldn't care. – GrumpyCrouton Jun 03 '16 at 16:29
  • Have you tried `ECHO timeout is set to %timeout%` just before it is used by `ping`? What was the result? Does it exhibit these symptoms if you hardcode a number instead of a variable? – lit Jun 03 '16 at 16:35
  • 1
    @GrumpyCrouton re-read the [first comment on your previous question](http://stackoverflow.com/q/37613046/1683264) re: delayed expansion. It should be `!timeout!` rather than `%timeout%`. – rojo Jun 03 '16 at 16:37
  • @rojo Ah, back at it again rojo. The suggestion I saw regarding delayed expansion didn't mention anything about that. Thank you. Should every single `%timeout%` be changed to `!timeout!`? – GrumpyCrouton Jun 03 '16 at 16:39
  • Do you have `timeout` in your global environment? (Is that the right term?) In the `else` you don't set a value for it. – shawnt00 Jun 03 '16 at 16:47
  • @shawnt00 Yes, it is set with all my other variables originally to 2 - and changes depending on connections. – GrumpyCrouton Jun 03 '16 at 16:52
  • @GrumpyCrouton So that's in another script? Is this `else` case the one that causes the unexpected wait? – shawnt00 Jun 03 '16 at 16:55
  • Think of it this way. The batch interpreter parses the parenthetical code block in one big clump. Variables are expanded before the block is evaluated. So the value of `%timeout%` has the same value at the end of the block as it did at the beginning. If you want to delay expansion of `%timeout%` until such time the line it lives in is executed, use `!timeout!` instead. – rojo Jun 03 '16 at 16:56
  • No, it's in the same script, just above the if/if else statements. And yes. But I believe it to be fixed with Rojo's suggestion. – GrumpyCrouton Jun 03 '16 at 16:56
  • @rojo Thank you for that explanation – GrumpyCrouton Jun 03 '16 at 17:01
  • @rojo I was actually incorrect, I noticed it is still doing it. – GrumpyCrouton Jun 03 '16 at 20:31
  • you don't have some `timeout.bat` lying around somewhere, do you? (maybe a relic of some testing in the past) (check with `where timeout`) – Stephan Jun 09 '16 at 05:59
  • @Stephan Not possible, the file is loaded onto flash drives and ran from there via command line, these flash drives contain only the file in question. – GrumpyCrouton Jun 09 '16 at 12:53
  • maybe somewhere within the `%path%`? `where timeout` would show that. Rule#1: don't trust anything or anyone - doublecheck everything. – Stephan Jun 09 '16 at 13:12
  • @Stephan I don't think I understand what you mean by that – GrumpyCrouton Jun 09 '16 at 13:26
  • just execute `where timeout`. If it shows nothing but "C:\Windows\System32\timeout.exe", I'm wrong. Background: This is a really weird and unheard behavour for the original `timeout.exe`, so I assume, there might be some other utility with the same name somewhere within your path. – Stephan Jun 09 '16 at 13:43
  • @Stephan The problem is, as I said, these batch files are ran from USBs with nothing on them, on computers that are factory installs on their language screens. There is no possible way another timeout command could be causing this. – GrumpyCrouton Jun 09 '16 at 20:26
  • Might want to take a look here: http://stackoverflow.com/questions/8192318/why-does-delayed-expansion-fail-when-inside-a-piped-block-of-code – Christopher G. Lewis Jun 15 '16 at 15:23
  • @Christopher_G_Lewis I'm not using pipes that I know of. – GrumpyCrouton Jun 15 '16 at 16:04
  • You are. First, in the Ping | Find line, and then you're using redirection (the && and || commands) which are starting new CMD spaces for each of the () blocks. – Christopher G. Lewis Jun 15 '16 at 16:27
  • You also might want to refactor your && and || blocks by using `Ping | find & If %errorelevel%==0 ( echo OK & GOTO :EOF)` – Christopher G. Lewis Jun 15 '16 at 16:42

2 Answers2

2

Here's a left-field thought, brought about by your comment

(it only happens when the device successfully connects to the internet, but not every time the device connects to the internet)

Before it connects to the internet, is the date, time and timezone correct? Connecting will synchronise the time - which may muck up your timeouts!

Like I said: left-field, but...

John Burger
  • 3,662
  • 1
  • 13
  • 23
  • 1
    when changing the time from another cmd window while running a `timeout 300`, the "waiting for ..." prompt indeed changes the remaining time accordingly. So you may have a point. – Stephan Jun 13 '16 at 05:32
  • You seem to be right. Timeout calculates the remaining time from a start time against the current time. This technic is always a bad idea, but therefore it seems to be the way for microsoft. But even the old python (2.x) versions uses this technic for timeouts – jeb Jun 13 '16 at 06:24
  • It is possible some of the computers are not in the correct timezone. What can I do to solve this? – GrumpyCrouton Jun 13 '16 at 12:55
  • @Grumpy Timezone should only be a problem if it changes. The code gets the current time, then starts waiting. If _something_ happens to change the time/timezone, then that could easily change the calculations involved. If you're saying that the device is at timezone X, starts your code, connects to the internet, and changes to timezone Y? That's a problem: once. If, however, it can change back to timezone X again (when disconnected?), then its a problem always. Which is it? – John Burger Jun 13 '16 at 13:00
  • @JohnBurger I never said it does it more than once. We only run the script on each computer once each. I feel like this is as close to the problem that anyone has come up with. Is there a way to change timezones via batch file? – GrumpyCrouton Jun 13 '16 at 13:31
  • I didn't realise it was an install/provisioning scenario - so now you're outside my ken. Sorry! – John Burger Jun 13 '16 at 13:36
1

choice seems not to be affected by the mentioned behaviour of timeout: "when changing the time from another cmd window while running a timeout 300, the "waiting for ..." prompt indeed changes the remaining time accordingly".

So instead of timeout /t !timeout! you can use

choice /n /c yn /d y /t !timeout!

/c yn is just for making it language independent.

Stephan
  • 53,940
  • 10
  • 58
  • 91
  • Is there a way to enable a countdown for this? – GrumpyCrouton Sep 28 '16 at 19:31
  • Kind of - you can build a loop around `choice /t 1` - but that won't be very exact and the differences would sum up more and more the longer the loop runs. And there is no chance to compensate, because the difference depends on workload, which isn't predictable. – Stephan Sep 29 '16 at 05:31