0

I've not had to write much batch file code in the past and I'm trying to understand why someone else's code has failed by writing a test batch file. My code:

:DoUntil
type p.txt >> log.txt
if %ERRORLEVEL% EQU 0 goto DoUntil

ECHO %ERRORLEVEL%

p.txt is an existing text file with a simple character string as is log.txt.

I then run this twice to get the error:

The process cannot access the file because it is being used by another process.

As you'd expect. Now I expected ERRORLEVEL to be set and a value returned by the echo, so what am I doing wrong please in ordered to get this echo'd as I expected? (it never hits the echo)

Or is there anywhere I can get a list of "type"s possible return value? I've found Googling on this subject quite frustrating due to how commonly used all the terms are! I read a few other questions on here which helped me correct one problem with my sample code but not the fundamental.

Edit:

Jeb's answer below was perfect in answering my query but I'm failing to take it forward. The problem code we have is like:

:DoUntil
type p.txt >> log.txt
if ERRORLEVEL 1 goto DoUntil

So the code is trying to say "if type fails, retry until it works". Are we saying by not having the "|| rem" clause+empty statement at the end of the type that the if statement is essentially doing nothing?

Community
  • 1
  • 1
Paul
  • 1,041
  • 11
  • 26

2 Answers2

3

There seems to be a bug/feature exists with errors from redirections. So you need a small trick to get the errorcode.

:DoUntil
type p.txt >> log.txt || rem
if %ERRORLEVEL% EQU 0 goto DoUntil

ECHO %ERRORLEVEL%

It's described by dbenham here

Community
  • 1
  • 1
jeb
  • 78,592
  • 17
  • 171
  • 225
  • Thanks that indeeds works for the sample. Do you possibly have time to look at the edit (that I'm about to make)? – Paul Jun 28 '12 at 10:50
3

In answer to your last question in your updated answer - It's not quite that simple. If the redirection succeeds but the TYPE fails (maybe p.txt doesn't exist), then IF will properly catch the ERRORLEVEL returned by TYPE. But if redirection fails then the TYPE is never executed and ERRORLEVEL is not properly set. So the subsequent IF is testing the value of ERRORLEVEL that existed prior to your statement running.

Again, the fix is to use the || operator. Any command could be used besides REM as long as the command is successful and it does not set the ERRORLEVEL to 0 upon success. The || operation actually sets the ERRORLEVEL to the result of the failed redirection. The following command has the potential to further set the ERRORLEVEL. REM is probably the safest thing you can use after || to guarantee the final ERRORLEVEL is what you want.

Here is a variation of the fix that combines the last 3 lines into 1 and does not use REM

@echo off
setlocal enableDelayedExpansion
:loop
echo hello>test.txt && goto loop || echo !errorlevel!

Or, without using delayed expansion

@echo off
:loop
echo hello>test.txt && goto loop || call echo %%errorlevel%%

We can't simply use || echo %errorlevel% because %errorlevel% would be expanded while the statement is parsed, which is before the redirection has a chance to fail.

dbenham
  • 127,446
  • 28
  • 251
  • 390