1

I have a simple batch script that will read the value in file version.property and perform a certain job my code is below

TITLE StartEODMaintenance
echo off
cls
set "Build=0"

call:FindString "MAINALGO"
IF /I "%Build%" == "MAINALGO" (
echo "start job on MainAlgo"
) else (
    call:FindString "DRSITEALGO"
    echo build value %Build%
    IF /I "%Build%" == "DRSITEALGO" (
        echo "start job on secondAlgo"
    ) else (
    echo "sth wrong"    
    )
)

:FindString
echo funtioninput %~1
find /I /C "%~1" version.property
if %errorlevel%==1 (
echo "errorlevel 1"
set "Build=0"
)
if %errorlevel%==0 (
echo "errorlevel 0" 
set "Build=%~1"
echo build value in function %Build%
)
:end 

The content in version.property is below

DRSITEALGO

The problem is I found that when the program is executed it looks like the below line work incorrectly. The variable Build is not set to the value in "%~1"

set "Build=%~1" 

I got the below as output

funtioninput MAINALGO

---------- VERSION.PROPERTY: 0
"errorlevel 1"
funtioninput DRSITEALGO   ---> the %~1 show the correct value, DRSITEALGO   

---------- VERSION.PROPERTY: 1    
"errorlevel 0"
build value in function 0   ---> here is wrong! the Build variable somehow didn't get updated, it suppose to be DRSITEALGO   
build value 0
"sth wrong"

Not sure that I have to set anything to make it works??

tune
  • 85
  • 2
  • 6

2 Answers2

1

The %variables% are expanded when the command is parsed and the command if followed by a block is parsed at once. So when you set a variable in the block, its following usage (in echo here) has been expanded already and it results in showing the value that was valid before entering the block!

You need delayed expansion to read variable values at the moment when they are used, not parsed. First, issue the command:

setlocal EnableDelayedExpansion

Then refer to the variables modified earlier within the same block as !variable!.

if %errorlevel%==0 (
echo "errorlevel 0" 
set "Build=%~1"
echo build value in function !Build!
)
Melebius
  • 6,183
  • 4
  • 39
  • 52
  • It doesn't appear that he's ever trying to retrieve a value modified within a code block. I don't think premature expansion is the problem. **Edit:** Well, he does `echo build value in function %Build%`, but that would only result in a cosmetic problem. That's easily fixed by changing `%Build%` to `%~1`. – rojo Aug 05 '15 at 15:37
  • Adding change to !Build! inside the :FindString make the program echo the correct value, how about if I want to access the Build variable in the main section, do I have to use the syntax !Build! all the time? – tune Aug 06 '15 at 03:49
  • @tune No, after you exit the block, you can use `%variable%` again. And pay attention to nested blocks, the _most outer one_ must be finished. You can check it by adding another `echo` command. And as @rojo suggests, you should place an `exit /b` command before the `:FindString` definition. – Melebius Aug 06 '15 at 06:32
0

The big problem is that your script continues to :FindString as part of the main runtime. On line 6 you call :FindString "MAINALGO", then you've got an IF code block. After that code block, you should exit /b or goto :EOF or something to halt execution of the main runtime, but you don't. Instead, your script continues to :FindString a second unintended time, sets %ERRORLEVEL% by find /I /C "" version.property, and continues to the end.

Something else you might find interesting is conditional execution. Instead of

find /I /C "%~1" version.property
if %errorlevel%==1 (
echo "errorlevel 1"
set "Build=0"
)
if %errorlevel%==0 (
echo "errorlevel 0" 
set "Build=%~1"
echo build value in function %Build%
)

... or ...

find /I "%~1" version.property
if errorlevel 1 (
    echo "errorlevel 1"
    set "Build=0"
) else (
    echo "errorlevel 0" 
    set "Build=%~1"
    echo build value in function %Build%
)

... you could condense your code a bit like this:

find /I "%~1" version.property && (
    echo "errorlevel 0" 
    set "Build=%~1"
    echo build value in function %Build%
) || (
    echo "errorlevel 1"
    set "Build=0"
)

I also recommend that you avoid being lazy with your indenting and formatting. While your code isn't nearly as bad as it could be, it would still be a little easier to see what's going on in :FindString if you indent your code blocks.

Anyway, see whether you have better luck with this:

TITLE StartEODMaintenance
echo off
cls
set "Build=0"

call :FindString "MAINALGO"

IF /I "%Build%"=="MAINALGO" (
    echo "start job on MainAlgo"
) else (
    call :FindString "DRSITEALGO"
    echo build value %Build%
    IF /I "%Build%"=="DRSITEALGO" (
        echo "start job on secondAlgo"
    ) else (
        echo "sth wrong"
        rem // exit non-zero
        exit /b 1
    )
)

exit /b 0
rem // end main runtime / begin script functions

:FindString
find /I "%~1" version.property && (
    echo "errorlevel 0" 
    set "Build=%~1"
    echo build value in function %~1
) || (
    echo "errorlevel 1"
    set "Build=0"
)
Community
  • 1
  • 1
rojo
  • 24,000
  • 5
  • 55
  • 101