views:

535

answers:

5

In a Windows batch file, I am taking an optional parameter that allows the caller to jump to the middle of the batch file and resume from there.

For example:

if [%1] neq [] (
echo Starting from step %1
goto %1
if %errorlevel% neq 0 goto error
)

:step1

:step2

...

goto end
:error
echo Error handler
...

:end

If the supplied parameter is not a valid label, the batch file immediately exits with the error The system cannot find the batch label specified.

Is there any way for me to handle this error and either execute my error handler block, or resume execution of the entire batch file, as if no parameter had been supplied?

+2  A: 

call :label spits out the error doesn't spit out an error when stderr is redirected (thanks, Johannes), and doesn't appear to change the error level, but continues with the batch file. You could set a variable after a label to indicate whether execution got that far.

@echo off
call :foo 2>nul
echo %errorlevel%
:bar
echo bar

yields

C:\>test.cmd
The system cannot find the batch label specified - foo
1
bar
C:\>
Anonymous
You can use 2>nul after the call to suppress the error message output.
Joey
Ah, thanks. I tried >nul, and it didn't do a thing.
Anonymous
A: 

I don't think that Windows batch files support any error handling (except if errorlevel...). You will need to validate the passed value is a valid label before the goto.

If at all possible I would recommend using PowerShell which is a far richer language and includes exception based error handling.

Richard
+7  A: 

You could try using findstr on the batch locating the goto target:

findstr /r /i /c:"^:%1" %0>nul
if errorlevel 1 goto error

It's a bit of a hack, but should work.

Joey
self-parsing batch files! neat.
Anonymous
Coding With Style: If the batch file's name includes spaces, then `%0` already contains quotes (otherwise you couldn't have run the batch in the first place). With `%~0` you're just stripping the quotes and re-adding them.
Joey
Huh, learn something new every day. That's completely nonstandard behavior, but I can see why they did that.
Coding With Style
+1  A: 

I probably would do it like this.

ECHO Starting from %1
IF "%1" == "step1" GOTO :step1 
IF "%1" == "step2" GOTO :step2
IF "%1" == "step3" GOTO :step3
IF "%1" == "step4" GOTO :step4
ECHO %1 is not valid label name
Stefan Steinegger
A: 

Thanks all, for this tidbit about batch files and labels. After some testing, I have this to add:

The test for ERRORELVEL after the call retains any old error level. E.g., the ERRORLEVEL value doesn't change until some command explicitly sets it.

So, here was my test, and my fix:

@echo off
for %%L in (1 2 3) do call :test %%L
goto:EOF
:test
call :_%1 %1 2>nul
if     "%ERRORLEVEL%"=="0" echo Label _%1 exists
if NOT "%ERRORLEVEL%"=="0" echo Label _%1 missing
goto:EOF
:_1
:_3
echo in routine %1
REM goto:EOF does not set ERRORLEVEL
REM exit /b N does set ERRORLEVEL
exit /b 0
:end

Expect to see:

in routine 1
Label _1 exists
Label _2 missing
in routine 3
Label _3 exists

Having the procedure end with "exit /b 0" explicitly resets the eror level to 0. Using "goto:eof" does not explicitly change the error level. You can, in fact, set the error level to values other than 0.

-Jesse

Jesse Chisholm