Friday, June 13, 2008

Commands from cmd does not set errorlevel as you might expect!

It might not be a surprise to you, but Windows commands inside cmd.exe does not change errorlevel as you might expect.

For example running a echo something > c:\somefile.txt, which will succeed actually creating the file, but not change errorlevel to 0. You can test it like this:

md 2>nul
echo %errorlevel%
1
echo this.works > c:\test.txt
echo %errorlevel%
1
type c:\test.txt
this.works

This echo can not really be solved by using cmd /c echo because that will just always succeed, for example:

md 2>nul
echo %errorlevel%
1
cmd /c echo this.works > c:\test.txt
echo %errorlevel%
0
type c:\test.txt
this.works
cmd /c echo this.fails > drivedoesnotexist:\test.txt
The filename, directory name, or volume label syntax is incorrect.
echo %errorlevel%
0


And now, testing if copy command file1 + file2 into file3 gives errorlevel 1 if one of the source files does not exists. Errorlevel 1 is what you might expect, but it is not the case here:

echo 1 > 1.txt
rm 2.txt
echo 3 > 3.txt
ls -la 2.txt
ls: File or directory "2.txt" is not found
copy /b 1.txt + 2.txt + 3.txt 123.txt
1.txt
3.txt
1 file(s) copied.
echo %errorlevel%0

This is not as I expected, I will want to find a way to get around this.

There are probably same problem with other cmd commands, I didnt try others.

Maybe I am doing something the wrong way, in my environment and installation ... need to investigate :-)

I have not been able to find anything in the cmd command line reference, and it does not seem to solvable if everything is put into a batch script, instead of running commands one by one. I did hope that, because of text on information about setlocal ENABLEEXTENSIONS which can be set in a script, but has no effect on the command prompt:

cmd does not set the ERRORLEVEL variable when command extensions are
disabled

But unfortunately it did not work, here is the run.cmd script i ran:

setlocal ENABLEEXTENSIONS
echo 1 > c:\1.txt
rm c:\2.txt
echo 3 > c:\3.txt
copy /b c:\1.txt + c:\2.txt + c:\3.txt c:\123.txt
echo %errorlevel%
endlocal

The above echo'd 0 and the errorlevel after the script is 0. So not a solution!

I still keep investigating :-)

Oh yeah - in case you ever wondered, you should never manually set the errorlevel to 0 or 1 or whatever you need. Instead you should always use a command for that. I am using "ver" to get errorlevel 0 and "md;2>nul" to get errorlevel set at 1, which I found on one of my favorite batch example webpages.

8 comments:

Unknown said...

Hi Copenhagens,

I am also facing same issue.
Could you please let me know, if you have any solution.

Regards,
Thiru

Unknown said...

my mail id

J said...

Well not really, but I made some additional errorchecking in my scripts:

For example checking that input files exist before copying, or that directories are found before echoing into files. This way I can force a return code 1 if something is not as expected.

Maybe someone can come up with something better later :-)

Anonymous said...

I'm going crazy with these errorlevels on Win Server 2003 r2. Scripts that worked fine on XP don't work at all here. Glad to see this post, though. Maybe I can try some of these suggestions.

Anonymous said...
This comment has been removed by the author.
Anonymous said...

I was kinda hard working and I finally gotta solution for that issue.


This is how you do it:

A and B are commands of the script you like to execute:

cmd /k "echo echo A ^> script.bat > createscript.bat & echo echo B ^>^> script.bat>>createscript.bat & echo set el=errorlevel^&>>createscript.bat & echo echo exit %%%el%%% ^>^> script.bat >> createscript.bat & echo script.bat >> createscript.bat & createscript.bat"


Well its not straight forward but it has some advantages:

good:
- one line command
- we may run any cmd command in any prio
- we also can run multiple commands, whole scripts
- we get the return value back through cmd

bad:
- script.bat and createscript.bat are left there as junk.

J said...

Sulai, i already get correct errorlevel from executing a wrong binary:

C:\>ver

Microsoft Windows XP [Version 5.1.2600]

C:\>echo %errorlevel%
0

C:\>A
'A' is not recognized as an internal or external command,
operable program or batch file.

C:\>echo %errorlevel%
9009


But what i had to workaround was this:

C:\>ver

Microsoft Windows XP [Version 5.1.2600]

C:\>echo %errorlevel%
0

C:\>echo this.fails > drivedoesnotexist:\test.txt
The filename, directory name, or volume label syntax is incorrect.

C:\>echo %errorlevel%
0

I would like that echo that failed to give a return code different from 0!

Anonymous said...

Good post, I more like it Copenhagen!
{Copenhagen}