batch-filecmdsubroutineerrorlevel

Using %ERRORLEVEL% to return a value from subroutine in batch script


I've been echoing my way through the following code but I cannot determine why %ERRORLEVEL% is always zero.

@echo off

set activePerl_SiteBinPath=D:\ProgramFiles\ActivePerl\site\bin
call :isInPath %activePerl_SiteBinPath% & set foundActivePerl_SiteBinPath=%ERRORLEVEL%
echo %foundActivePerl_SiteBinPath%

set blub=d:\blub
call :isInPath %blub% & set foundBlub=%ERRORLEVEL%
echo %foundBlub%
exit /b

:isInPath
::  Tests if the path stored within variable pathVar exists within %PATH%.
::
::  The result is returned as the ERRORLEVEL:
::      0 if pathVar is found in %PATH%.
::      1 if pathVar path is not found in %PATH%.
::      2 if parhVar path is missing/undefined.

:: Error checking
if "%~1"=="" exit /b 2

set pathVar=%~1
for /f %%i in ('echo ";%%PATH%%;" ^| find /c /i ";%pathVar%;"') do (
    set /a foundPathVar=%%i
)
if /i %foundPathVar% equ 0 (
    exit /b 1
)
set foundPathVar=0
exit /b 0

I get the following output

0
0

but I would expect

0
1

and according to the echoing I did inside :isInPath for case one exit /b 0 and for case two exit /b 1 is called. But why is %ERRORLEVEL% zero in both cases? I totally don't get it. Please help!


Solution

  • In cmd the whole line will be parsed for variable substitution at once. Hence at the time the following line is executed errorlevel is 0

    call :isInPath %blub% & set foundBlub=%ERRORLEVEL%
    

    You need to use delayed expansion

    SETLOCAL EnableDelayedExpansion
    call :isInPath %blub% & set foundBlub=!ERRORLEVEL!