Friday, May 07, 2010

The joy's of batch - Delayed Expansion

 

If you can, skip batch and move strait to powershell. If you don't believe me, maybe this blog post will change your mind. In batch %ErrorLevel% is how you know if the last command succeeded:

C:\>echo %ERRORLEVEL%
0
It turns out if you set a variable that doesn't exist, this sets error code to 1. So
C:\>set DONKEYRIDING
Environment variable DONKEYRIDING not defined

C:\>echo %ERRORLEVEL%
1
Makes sense, batch isn't that bad you think. Now here's a pop quiz - What will you get when you run this batch file?
C:\>type foo.bat
if NOT "BATCH"=="OBVIOUS" (

        echo %ERRORLEVEL%
        set DONKEYRIDING
        echo %ERRORLEVEL%

)
I"ll run it for you:
C:\>foo.bat

C:\>if NOT "BATCH" == "OBVIOUS" (
echo 0
 set DONKEYRIDING
 echo 0
)
0
Environment variable DONKEYRIDING not defined
0
C:\>
Not what you thunk huh? Maybe error level wasn't set - lets check
C:\>echo %ERRORLEVEL%
1
What the heck happened? Well, the if block is a statement, and variable substation happened when the statement was read.  You don't want this behavior and you’re probably not interested in the details, luckily batch has something called delayed variable expansion, which you expose using !ERRORLEVEL! so you need to change your batch file to be:
setlocal ENABLEDELAYEDEXPANSION
if NOT "BATCH"=="OBVIOUS" (
	echo !ERRORLEVEL!
	set DONKEYRIDING
	echo !ERRORLEVEL!
)
Which gives the expected output:
C:\>foo2.bat

C:\>setlocal ENABLEDELAYEDEXPANSION

C:\>if NOT "BATCH" == "OBVIOUS" (
echo !ERRORLEVEL!
 set DONKEYRIDING
 echo !ERRORLEVEL!
)
0
Environment variable DONKEYRIDING not defined
1
C:\>
As I said, skip batch and go strait to powershell!

No comments: