SpaghettiCode
SpaghettiCode

Reputation: 327

How to pass an error message occuring inside the FOR /F loop body into the FOR parameter in Batch

I was wondering if I can capture error messages directly (just like an output from a successfully executed command would be) and do whatever I want with it, such as storing it in a variable, or passing it as a parameter.

Here's what I'm trying to do lately. Please check the code:

FOR /F "tokens=2 delims== " %%s IN (
    'WMIC DISKDRIVE WHERE SerialNumber^="sn999" GET SerialNumber /VALUE'
) DO (
    IF "%%s"=="sn999" (GOTO Label1) ELSE (GOTO Label2)
)

What I'm trying to do here is to check if a particular external hard drive is plugged-in by comparing the serial number, and from then, the code will determine which path to take. It works as intended if the desired external hard drive is plugged-in. However, if the external hard drive with the same serial number is not plugged-in, I get the following message:

No Instance(s) Available.

And as a consequence I get these issues:

My research led me to these sources:

Redirecting Error Messages from Command Prompt: STDERR/STDOUT

Display & Redirect Output

Both links discuss redirecting error messages. I thought I can just write few lines of code to redirect error messages to a text file, recover it and parse the contents, and finally clean it up. But I'm not sure if this is the best idea though. So, I'd appreciate any suggestion that you may have that may work with the code above. Also, I'd like to know why %ERRORLEVEL% is 0 even though I got an error message. Lastly, I'd like to know if it is possible to capture error messages without writing anything to the hard drive.

Thank you all very much!!

Upvotes: 1

Views: 147

Answers (3)

Compo
Compo

Reputation: 38623

I see no reason to use a For loop in this instance because a metavariable is not required.
The For loop runs the WMIC command in another instance of cmd.exe unnecessarily.

@Echo Off
WMIC DiskDrive Where SerialNumber="sn999" List Instance 2>Nul|Find "I">Nul && GoTo :Label1
Echo Drive Not Found & Pause
GoTo :EOF

:Label1
Echo Drive Found & Pause
GoTo :EOF

Upvotes: 0

michael_heath
michael_heath

Reputation: 5372

Put GOTO Label2 after the loop. If GOTO Label1 is triggered, then the GOTO Label2 will be avoided as it will jump to the label.

FOR /F "tokens=2 delims== " %%s IN (
    'WMIC DISKDRIVE WHERE SerialNumber^="sn999" GET SerialNumber /VALUE'
) DO (
    IF "%%~s"=="sn999" GOTO Label1
)
GOTO Label2

You could also suppress the stderr message of No Instance(s) Available. with 2^>nul if you prefer.

Upvotes: 1

user7818749
user7818749

Reputation:

Using findstr makes you able to use errorlevel.

@echo off
for /F %%i in ('WMIC DISKDRIVE ^| findstr /I /C:"sn999"') do if %errorlevel%==0 echo Drive Found & goto :EOF
echo Drive not Found.

This basically does a search on the string and if found sets errorlevel to 0, if not found errorlevel will be 1.

If errorlevel is 0 then it will echo Drive Found and goto :EOF if errorlevel is not 1, it skips the line as the condition was not met and it will echo Drive not Found.

If you still want to use the labels, then simply do:

@echo off
for /F %%i in ('WMIC DISKDRIVE ^| findstr /I /C:"sn999"') do if %errorlevel%==0 goto :label1

REM This will act as label2
echo Drive not found
goto :EOF

:label1
echo Drive found
goto :EOF

Note we do not have to use goto label2 as it will automatically go passed the errorlevel match and continue, only label1 is really needed then.

Upvotes: 0

Related Questions