EDIT - barebones code added in the P.S. to better describe the root problem, which also verifies Dave's neat resolution posted below.
EDIT #2 - added code to cover the case of a piped command, and also Jeb's alternative solution.
Question arose in the context of attempting to distinguish between an empty vs. a missing value in a reg query /v. The code below does work as expected, but is not able to retrieve the actual errorlevel, only to detect failure vs. success. Specifically, the "1" in "echo ErrorLevel%%TAB%%reg_failed%%TAB%%1" is hardcoded, and I found no obvious syntax to replace it with the actual %errorlevel% returned by "reg".
Code: Select all
@echo off
setlocal disableDelayedExpansion
@rem this must be a literal TAB character
set "TAB= "
set "KEY=%~1"
set "VAL=%~2"
if "%VAL%"=="" (set $VAL=@) else (set $VAL="%VAL%")
echo. & echo [%KEY%]
call :regQuery "%KEY%" "%VAL%" DATA TYPE
if errorlevel 1 ( echo %$VAL%=
) else if "%TYPE%"=="REG_SZ" ( echo %$VAL%="%DATA%"
) else ( echo %$VAL%="%TYPE%:%DATA%")
endlocal
goto :eof
:: %1 [input, required] registry key
:: %2 [input, optional] value to be queried, default value if missing
:: %3 [output, optional] name of variable to receive the data
:: %4 [output, optional] name of variable to receive the data type
::
:: returns errorlevel 0 when OK, 1 if failed e.g. key/value doesn't exist
::
:: to do: capture/return actual !errorlevel! from 'reg' vs. hardcoded '1'
::
:regQuery
if not "%~3"=="" (set "%~3=" & if not "%~4"=="" set "%~4=")
@rem 'reg query /ve' for the default value, 'reg query /v' otherwise
@rem catch 'reg' failure, build and echo a string for 'find' to recognize
@rem check output for the error signature, exit accordingly
for /f "tokens=1,2,* delims=%TAB%" %%a in (
'^(^(if "%~2"^=^="" ^(reg query "%~1" /ve^) ^
else ^(reg query "%~1" /v "%~2"^)^) 2^>nul ^
^|^| echo ErrorLevel%%TAB%%reg_failed%%TAB%%1^) ^
^| find /i "REG_"'
) do (
if "%%~b"=="reg_failed" (
if "%%~a"=="ErrorLevel" (
@rem 'reg' failed, or highly unlikely false negative
exit /b %%~c
) else (
@rem unexpected 'reg_failed' data type, or unlikely false positive
)
)
@rem data to be returned, possibly none
if not "%~3"=="" (set "%~3=%%~c" & if not "%~4"=="" set "%~4=%%~b")
)
exit /b 0
FWIW "reg" is documented to only ever return 0 or 1, so this is not an issue in this particular case. However, it may matter in other cases, therefore the question.
Liviu
EDIT #2 - P.S. Leaving out the 'reg query' distractions, issue was about loops like this.
Code: Select all
@echo off
setlocal disableDelayedExpansion
set "p1Error=%%errorlevel%%"
cmd /c exit 1
for /f "tokens=1,2,3,4" %%a in ('cmd /c exit 9 ^|^| call echo %errorlevel% %%errorlevel%% %%^^errorlevel%% %%p1Error%%') do (
echo %%~a = errorlevel before the 'for' loop
echo %%~b = errorlevel of the new instance of cmd running the 'in' command, always 0
echo %%~c = %%~d = errorlevel returned by the master 'in' command
)
set "p2Error=%%p1Error%%"
cmd /c exit 1
for /f "tokens=1,2,3,4" %%a in ('^(cmd /c exit 9 ^|^| call echo %errorlevel% %%errorlevel%% %%^^^^errorlevel%% %%p2Error%%^) ^| more') do (
@rem echo %%~a = errorlevel before the 'for' loop
@rem echo %%~b = errorlevel of the new instance of cmd running the 'in' command, always 0
echo %%~c = %%~d = errorlevel returned by the piped master 'in' command
)
exit /b 0
Code: Select all
1 = errorlevel before the 'for' loop
0 = errorlevel of the new instance of cmd running the 'in' command, always 0
9 = 9 = errorlevel returned by the master 'in' command
9 = 9 = errorlevel returned by the piped master 'in' command
Original question was how to get the '9' values on the last lines. I had tried variations of call's and escaping, but missed the "obvious"
