Samselvaprabu
Samselvaprabu

Reputation: 18137

If condition is not being executed in for loop of batch file

We are calling msbuild command in batch files.

We have passed the parameters via for loop of batch file.

FOR %%C in (
    CommonInfrastructure
    CommonUtilities
    ) do ( 
        msbuild /t:%BuildCmdType% %BuildFile%  /p:Group=%%C %msbuildLogger% /p:Configuration=Release
        if %ERRORLEVEL% NEQ 0 (
        msbuild /t:SendFailureMail /p:ErrorLogFileName=%ErrorLog% %BuildFile%
        set ErrorBuild=1
        )
    )

When i analyzing the log file, I am seeing that code in If block is not being executed.

Due to that notification mails are not being sent.

How to make it to execute if condition ?

Upvotes: 1

Views: 221

Answers (2)

dbenham
dbenham

Reputation: 130809

jeb correctly diagnosed your problem and provided a good solution. You have other options.

IF ERRORLEVEL 1 ... (without percents) checks if the ERRORLEVEL is greater than or equal to 1. That should work as long as msbuild never returns a negative ERRORLEVEL.

FOR %%C in (
    CommonInfrastructure
    CommonUtilities
) do ( 
    msbuild /t:%BuildCmdType% %BuildFile%  /p:Group=%%C %msbuildLogger% /p:Configuration=Release
    if ERRORLEVEL 1 (
        msbuild /t:SendFailureMail /p:ErrorLogFileName=%ErrorLog% %BuildFile%
        set ErrorBuild=1
    )
)


You can test for any non-zero value without using expansion by use of a variable and IF (NOT) DEFINED

set "success="
FOR %%C in (
    CommonInfrastructure
    CommonUtilities
) do ( 
    msbuild /t:%BuildCmdType% %BuildFile%  /p:Group=%%C %msbuildLogger% /p:Configuration=Release
    if errorlevel 0 if not errorlevel 1 set success=1
    if not defined success (
        msbuild /t:SendFailureMail /p:ErrorLogFileName=%ErrorLog% %BuildFile%
        set ErrorBuild=1
    )
)


My preferred solution is to use the || operator to conditionally execute commands only if the prior command failed. (Note - there is also the && operator to conditionally execute upon success)

FOR %%C in (
    CommonInfrastructure
    CommonUtilities
) do ( 
    msbuild /t:%BuildCmdType% %BuildFile%  /p:Group=%%C %msbuildLogger% /p:Configuration=Release || (
        msbuild /t:SendFailureMail /p:ErrorLogFileName=%ErrorLog% %BuildFile%
        set ErrorBuild=1
    )
)

Upvotes: 4

jeb
jeb

Reputation: 82202

It's the type of parsing of batch files.
All percents in a block, anything inside parenthesis, is expanded at parse time not at execution time.
So your %errrorlevel% will be expanded excactly one time, before any command runs in your block. So it will normally always be zero.

To avoid this, there exists the delayed expannsion, use this instead.

!errorlevel! instead of %errorlevvel% And you need to activate it before you can use it (best in the second line of your batch script).

setlocal EnableDelayedExpansion

Upvotes: 4

Related Questions