I know that there must be some syntax issue on my end with this, but I can't for the life of me figure this out right now. This is a script I put together a few months back to automatically download some files for me as they release every month. It was working fine, however this month I noticed that nothing was downloading. After some troubleshooting and investigation, I found that the month variable was setting itself to "-1" instead of subtracting "1" from it's current value. As a result of this I'm unable to get the proper file name to attempt the download. It's the same match that I'm using on days, revision number, and year number, but for some reason the month variable just isn't cooperating with me and I can't figure out why.
:MASTER
@echo off
mode con:cols=100 lines=5
::Setup First Download
for /f "tokens=2*" %%a in ('REG Query "HKLM\SOFTWARE\Wow6432Node\ExampleRegistryKey" /v ExampleString 2^>nul') do set "ExampleDir=%%~b"
pushd "%ExampleDir%"
for /f "tokens=2 delims==" %%a in ('findstr SQLiteHome Example.ini') do set SQLiteHome=%%a
::Revision Number
set num=17
set /a "num=num-1"
::Begin set date
for /f "tokens=1-4 delims=/-. " %%i in ('date /t') do (call :set_date %%i %%j %%k %%l)
goto :end_set_date
:set_date
if "%1:~0,1%" gtr "9" shift
for /f "skip=1 tokens=2-4 delims=(-)" %%m in ('echo,^|date') do (set %%m=%1&set %%n=%2&set %%o=%3)
goto :eof
:end_set_date
set dd=31
This section here is where the month starts to equal -1 instead of current one subtracted from the current month.
set /a "mm=mm-1"
if %mm%==9 set mm=09
if %mm%==8 set mm=08
if %mm%==7 set mm=07
if %mm%==6 set mm=06
if %mm%==5 set mm=05
if %mm%==4 set mm=04
if %mm%==3 set mm=03
if %mm%==2 set mm=02
if %mm%==1 set mm=01
if %mm%==0 set /a "yy=yy-1"
if %mm%==0 set mm=12
Set EarlyEntry=early_up_sqlite_r
Set FullEntry=update_sqlite_r
Set MstarEntry=mstar_ext_sqlite_r
Set PSNEntry=psn_ext_sqlite_r
set CurrentEntry=%EarlyEntry%
set ThisFile=%CurrentEntry%%num%_%yy%%mm%%dd%.exe
ECHO %ThisFile%
set INIentry=EarlyLast
::Create %WorkingDirectory%\Dates.txt and Downloads.ini
set INIfile=C:\ProgramData\SA_Updater\Downloads.ini
set WorkingDirectory=C:\ProgramData\SA_Updater\
set OldDownloads=C:\ProgramData\SA_Updater\Downloads\
set PSNini=PSNLast
set MSTARini=MSTARLast
set Fullini=FullLast
set Earlyini=EarlyLast
echo %PSNini%
echo Dates > %WorkingDirectory%\Dates.txt
if not exist "%WorkingDirectory%" mkdir "%WorkingDirectory%"
if not exist "%OldDownloads%" mkdir "%OldDownloads%"
pusd %WorkingDirectory%
if not exist "%INIfile%" (
ECHO %PSNini%= > %INIfile%
ECHO %MSTARini%= >> %INIfile%
ECHO %Fullini%= >> %INIfile%
ECHO %Earlyini%= >> %INIfile%
)
:ObtainVariables
::Find the Last version downloaded
This is where I've kept a log for the download attempts echo Dates > %WorkingDirectory%\Dates.txt The output is looking like this:
Dates
http://Example.com/updates/early_up_sqlite_r16_2018-131.exe
http://Example.com/updates/early_up_sqlite_r15_2018-131.exe
http://Example.com/updates/early_up_sqlite_r14_2018-131.exe
Instead of:
Dates
http://Example.com/updates/early_up_sqlite_r16_20180731.exe
http://Example.com/updates/early_up_sqlite_r15_20180731.exe
http://Example.com/updates/early_up_sqlite_r14_20180731.exe
The rest of the script:
for /f "tokens=2 delims==" %%a in ('findstr %INIentry% %INIfile%') do set LastINIfile=%%a
ECHO %LastINIfile%
::Revision Number
set num=17
set /a "num=num-1"
::Begin set date
for /f "tokens=1-4 delims=/-. " %%i in ('date /t') do (call :set_date %%i %%j %%k %%l)
goto :end_set_date
:set_date
if "%1:~0,1%" gtr "9" shift
for /f "skip=1 tokens=2-4 delims=(-)" %%m in ('echo,^|date') do (set %%m=%1&set %%n=%2&set %%o=%3)
goto :eof
:end_set_date
set dd=31
set /a "mm=mm-1"
if %mm%==9 set mm=09
if %mm%==8 set mm=08
if %mm%==7 set mm=07
if %mm%==6 set mm=06
if %mm%==5 set mm=05
if %mm%==4 set mm=04
if %mm%==3 set mm=03
if %mm%==2 set mm=02
if %mm%==1 set mm=01
if %mm%==0 set /a "yy=yy-1"
if %mm%==0 set mm=12
set ThisFile=%CurrentEntry%%num%_%yy%%mm%%dd%.exe
goto Download
:Download
::Setup Download Variables
cls
set Download=http://Example.com/updates/%ThisFile%
GOTO TryDownload
:TryDownload
::Add Download Attempt to %WorkingDirectory%\Dates.txt
echo %Download% >> %WorkingDirectory%\Dates.txt
::Is the file download? If so, start the install
cls
mode con:cols=100 lines=10
powershell "Import-Module BitsTransfer; Start-BitsTransfer '%Download%' '%DownloadDir%'"
mode con:cols=100 lines=5
cls
::ping localhost -n 3 >nul
if exist C:\ProgramData\SA_Updater\%ThisFile% (
GOTO StartInstall
) else (
::Try Downloading
GOTO TryAgain
)
cls
:TryAgain
set /a "num=num-1"
if %mm%==9 set mm=09
if %mm%==8 set mm=08
if %mm%==7 set mm=07
if %mm%==6 set mm=06
if %mm%==5 set mm=05
if %mm%==4 set mm=04
if %mm%==3 set mm=03
if %mm%==2 set mm=02
if %mm%==1 set mm=01
if %num%==0 set /a "dd=dd-1"
if %dd%==27 set /a "mm=mm-1"
if %mm%==0 set /a "yy=yy-1"
if %mm%==0 set mm=12
if %dd%==27 set dd=33
if %num%==0 set num=17
set ThisFile=%CurrentEntry%%num%_%yy%%mm%%dd%.exe
set Download=http://Example.com/updates/%ThisFile%
set DownloadDir=%WorkingDirectory%%ThisFile%
if %ThisFile% EQU %LastINIfile% GOTO CheckEarly
GOTO TryDownload
)
:StartInstall
%WorkingDirectory%%ThisFile% /w /v"INSTALLPREREQUISITES=0"
robocopy %WorkingDirectory% %OldDownloads% %ThisFile%
pushd %WorkingDirectory%
del %ThisFile%
del /Q /A H *.tmp
GOTO DoINIstuff
::Update ThisFile
:CheckEarly
if %CurrentEntry% EQU %EarlyEntry% GOTO SetupFull
GOTO CheckFull
:CheckFull
if %CurrentEntry% EQU %FullEntry% GOTO SetupMstar
GOTO CheckMstar
:CheckMstar
if %CurrentEntry% EQU %MstarEntry% GOTO SetupPSN
GOTO CheckPSN
:CheckPSN
if %CurrentEntry% EQU %PSNEntry% GOTO SetupEarly
GOTO CheckEarly
::Setups
:SetupFull
set CurrentEntry=%FullEntry%
set INIentry=%Fullini%
GOTO ObtainVariables
:SetupMstar
set CurrentEntry=%MstarEntry%
set INIentry=%MSTARini%
GOTO ObtainVariables
:SetupPSN
set CurrentEntry=%PSNEntry%
set INIentry=%PSNini%
GOTO ObtainVariables
:SetupEarly
set CurrentEntry=%EarlyEntry%
set INIentry=%Earlyini%
GOTO ObtainVariables
:DoINIstuff
SetLocal EnableDelayedExpansion
Set _PathtoFile=%INIfile%
Set _OldLine=%INIentry%=
Set _NewLine=%INIentry%=%ThisFile%
Call :_Parse "%_PathtoFile%"
Set _Len=0
Set _Str=%_OldLine%
Set _Str=%_Str:"=.%987654321
:_Loop
If NOT "%_Str:~18%"=="" Set _Str=%_Str:~9%& Set /A _Len+=9& Goto _Loop
Set _Num=%_Str:~9,1%
Set /A _Len=_Len+_Num
PushD %_FilePath%
If Exist %_FileName%.new Del %_FileName%.new
If Exist %_FileName%.old Del %_FileName%.old
Set _LineNo=0
For /F "Tokens=* Eol=" %%I In (%_FileName%%_FileExt%) Do (
Set _tmp=%%I
Set /A _LineNo+=1
If /I "!_tmp:~0,%_Len%!"=="%_OldLine%" (
>>%_FileName%.new Echo %_NewLine%
) Else (
If !_LineNo! GTR 1 If "!_tmp:~0,1!"=="[" Echo.>>%_FileName%.new
SetLocal DisableDelayedExpansion
>>%_FileName%.new Echo %%I
EndLocal
))
Ren %_FileName%%_FileExt% %_FileName%.old
Ren %_FileName%.new %_FileName%.ini
PopD
Goto :CheckEarly
:_Parse
Set _FilePath=%~dp1
Set _FileName=%~n1
Set _FileExt=%~x1
Goto :EOF
I hope I haven't omitted too much to figure this out. Basically, I can see that the revision number and the day are acting like they should, but the month just reverts to "-1" instead of actually performing the subtraction, and I'm basically pulling my hair out trying to figure out what I'm doing wrong.
The reason is quite simple. A number string with a leading 0
is interpreted as octal number by C function strtol used by cmd.exe
to convert a number string to an integer.
08
and 09
are invalid numbers in octal numeral system and for that reason function strtol
returns 0
which is subtracted next by 1
resulting in -1
.
The simple solution is using set /a "mm=1%mm%-101"
instead of set /a "mm=mm-1"
. Then first the month value is concatenated as string with the character 1
building the strings 101
to 112
and so the number string has no leading 0
anymore and from this number 101
is subtracted to get 0
to 11
assigned as string to environment variable mm
.
By the way: Use the following two command lines to get back the leading zero after subtraction:
set "mm=0%mm%"
set "mm=%mm:~-2%"
The first line concatenates 0
-11
to 00
-011
and the second line takes just the last two characters of this string resulting in 00
-11
assigned finally to environment variable mm
.
The next two lines should be replaced by: if %mm% == 00 set "mm=12" & set /a "yy-=1"