Reputation: 5578
I am trying to write a simple batch file which will control access to the computer (using shutdown) so for every 30 minutes when the computer is on, there has to be at least 30 minutes when the computer is off. The file will be put in auto start. The algorithm looks as follows:
Get from the file time when the computer was last closed (LASTCLOSETIME)
calculate BREAKUNTIL as LASTCLOSETIME + 30 minutes
if CURRENTTIME < BREAKUNTIL {
then shutdown now
} else {
shutdown in 30 minutes
save to the file CURRENTTIME + 30 minutes
}
I did not handle what happens in the first run if the file does not exist, but it is not a problem for now - a file exists and contains valid data.
The code I have:
::echo off
FOR /F "DELIMS=" %%G IN ('TIME /T') DO SET CURRENTTIME=%%G
echo %CURRENTTIME%
set /A CURRENTTIME = %CURRENTTIME:~0,2%*60 + %CURRENTTIME:~3,2%
echo %CURRENTTIME%
set /P LASTCLOSETIME=<lastclose.txt
set /A BREAKUNTIL = %LASTCLOSETIME% + 30
set /A BREAKUNTIL = %BREAKUNTIL% %% 1440
echo CURRENTTIME: %CURRENTTIME%
echo LASTCLOSETIME: %LASTCLOSETIME%
echo BREAKUNTIL: %BREAKUNTIL%
if "%CURRENTTIME%" LSS "%BREAKUNTIL%" (
shutdown -s -t 30
) else (
shutdown -s -t 1800
set CLOSETIME = %CURRENTTIME%
echo CLOSETIME: %CLOSETIME%
set /A CLOSETIME = %CLOSETIME% + 30
set /A CLOSETIME = %CLOSETIME% %% 1440
echo %CLOSETIME%
echo %CLOSETIME% > lastclose.txt
)
PAUSE
The problem is where I set CLOSETIME
. It successfully gets the value of CURRENTTIME
and I can see e.g. "set CLOSETIME = 886"
in the console but the next line does not print this time at all, as if a variable was not set. Does it have something to do with the if statement? I have tried using labels and goto statements but the result was the same.
Upvotes: 0
Views: 1488
Reputation: 79983
Standard DELAYEDEXPANSION problem.
This is ONE compound statement:
if "%CURRENTTIME%" LSS "%BREAKUNTIL%" (
shutdown -s -t 30
) else (
shutdown -s -t 1800
set CLOSETIME = %CURRENTTIME%
echo CLOSETIME: %CLOSETIME%
set /A CLOSETIME = %CLOSETIME% + 30
set /A CLOSETIME = %CLOSETIME% %% 1440
echo %CLOSETIME%
echo %CLOSETIME% > lastclose.txt
)
When the statement is PARSED, the CURRENT values of any %var%
are substituted and THEN the statement is executed. The value isn't ASSIGNED to closetime
until the statement is EXECUTED, hence the statement is interpreted as
if "%CURRENTTIME%" LSS "%BREAKUNTIL%" (
shutdown -s -t 30
) else (
shutdown -s -t 1800
set CLOSETIME = %CURRENTTIME%
echo CLOSETIME:
set /A CLOSETIME = + 30
set /A CLOSETIME = %% 1440
echo
echo > lastclose.txt
)
Easiest cure is to change this sequence to
if "%CURRENTTIME%" LSS "%BREAKUNTIL%" (
shutdown -s -t 30
GOTO :EOF
)
shutdown -s -t 1800
set CLOSETIME = %CURRENTTIME%
echo CLOSETIME: %CLOSETIME%
set /A CLOSETIME = %CLOSETIME% + 30
set /A CLOSETIME = %CLOSETIME% %% 1440
echo %CLOSETIME%
echo %CLOSETIME% > lastclose.txt
Note that GOTO :EOF
where the colon is required
means 'go to the physical end-of-file.
Second easiest is to execute
SETLOCAL ENABLEDELAYEDEXPANSION
somewhere before this IF
statement (commonly directly after the @echo off
) and change the IF
to
if "%CURRENTTIME%" LSS "%BREAKUNTIL%" (
shutdown -s -t 30
) else (
shutdown -s -t 1800
set CLOSETIME = %CURRENTTIME%
echo CLOSETIME: !CLOSETIME!
set /A CLOSETIME = !CLOSETIME! + 30
set /A CLOSETIME = !CLOSETIME! %% 1440
echo !CLOSETIME!
echo !CLOSETIME! > lastclose.txt
)
Noting that when DELAYEDEXPANSION
is in effect, !var!
returns the RUNTIME value of var
(ie as it changes) whereas %var%
returns the PARSE-TIME value of var
(ie as it stood when the statement was parsed, before execution.)
Upvotes: 1