My batch file is prematurely terminating when I run this in a cmd.exe that is NOT an MSVC development command shell.
msbuild /version | find "Microsoft (R) Build Engine version 16" >nul
echo did I get here?
if errorlevel 1 goto no_msbuild
I never get to the if errorlevel
line, so I added the echo did I get here?
line, and I don't get that either.
Here's the output when I run the .bat file (I removed the @echo off):
Wed 09/07/2022 10:37:49
D:\temp> msbuild /version | find "Microsoft (R) Build Engine version 16" 1>nul
'msbuild' is not recognized as an internal or external command,
operable program or batch file.
Wed 09/07/2022 10:37:49
D:\temp>
It works fine when I run it in a VS2019 cmd shell (if errorlevel 1 test is false, i.e. errorlevel is 0, so find worked) and a VS2008 cmd (if errorlevel 1 is true, so find failed)
EDIT: I eliminated the whole msbuild command/path issue, incorporating @mofi possible solution and came up with the following:
xyzzy 2>nul | find "abc"
echo hello
if errorlevel 1 goto no_xyzzy
The .bat file still terminates prematurely and never executes the echo hello
even with the stderr redirection to nul.
CodePudding user response:
Let me try and simplify this.
xyzz | find...
is piping the stdout
of xyzz
to find
. however, xyzz
does not exist and therefore does not have stdout
or stderr
streams, so it will terminate. cmd
however will produce 9009
errorlevel, but you did not request stdout
or stderr
from cmd
, you requested it from xyzz
becuE you piped it to find
To prove this point, we can eliminate find
xyzz 2>nul
if errorlevel 1 echo Failed
echo %errorlevel%
This will result in a result Failed
.
We can however parenthesize the command and pipe the block to find
.
(xyzz 2>nul) | find "abc"
if errorlevel 1 echo Failed
echo %errorlevel%
Firstly note, errorlevel
is now 1
and not 9009
, not because 9009
does not exist, it existed inside the parenthesis, but find
is overwriting errorlevel
Then, the reason this works is because the code block in its entirety is redirected to find
, that means the cmd
result as well, the entire block does not fail, only xyzz
does and the execution of the block completes, but now the find
query was not met and caused errorlevel 1
you can shorten this test by simply running:
xyzz 2>nul | find "abc" && echo success || echo failed
vs
(xyzz 2>nul) | find "abc" && echo success || echo failed
One last thing. .bat
is the old extension of batch-files
and it handles errorlevel slightly differently from the new .cmd
extensions. So rather use the new normal.