I have a batch file that is using the exit
command to return an exit code.
This batch file may, in some cases, be invoked interactively from a commandline, or in other cases, may be run as part of an MSBuild project, using the Exec
task.
- If I use
exit %errorlevel%
within my batch file this works well and MSBuild sees the error code, however an interactive user who is running the batch file from a command window will get a rude exit of cmd.exe in this case.
- If I use
exit /b %errorlevel%
the interactive scenario does not get a rude exit, but this also means that the cmd
launched by my Exec
task also does not exit, and therefore MSBuild does not see the return value.
As a solution to both problems, I am trying to use exit /b
but launch the batch file from my build script like this:
<Exec Command="Batch.cmd params & exit %errorlevel%" />
The idea being that I explicitly take the 'non-terminal' return from exit /b
and manually call exit
to propogate this value outside of cmd.exe
where the Exec
Build Task can see it.
This seems like the perfect solution, however it isn't working. Exec
still doesn't get the correct error value.
One way to handle this could be to have MSBuild pass a parameter to the batch file so that it knows that MSBuild is calling it instead of from a command prompt.
For example I have created the sample file test.bat shown below
ECHO OFF
IF (%1)==() goto Start
SET fromMSBuild=1
:Start
ECHO fromMSBuild:%fromMSBuild%
REM ***** Perform your actions here *****
set theExitCode=101
GOTO End
:End
IF %fromMSBuild%==1 exit %theExitCode%
REM **** Not from MSBuild ****
ECHO Exiting with exit code %theExitCode%
exit /b %theExitCode%
And I've created the MSBuild file wrapper.proj which is:
<Project DefaultTargets="Demo" ToolsVersion="3.5"
xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<BatchFile>test.bat</BatchFile>
<FromMSBuild>FromMSBuild</FromMSBuild>
</PropertyGroup>
<Target Name="Demo">
<Message Text="Executing batch file $(BatchFile)" Importance="high"/>
<PropertyGroup>
<_Command>$(BatchFile) $(FromMSBuild)</_Command>
</PropertyGroup>
<Exec Command="$(_Command)">
<Output PropertyName="CommandExitCode" TaskParameter="ExitCode"/>
</Exec>
<Message Text="CommandExitCode: $(CommandExitCode)"/>
</Target>
</Project>
If you execute the file test.bat from the command prompt the result is
C:\Data\Development\My Code\Community\MSBuild\BatchFile>test.bat
C:\Data\Development\My Code\Community\MSBuild\BatchFile>ECHO OFF
fromMSBuild:0
Exiting with exit code 101
And from MSBuild the result is:
C:\Data\Development\My Code\Community\MSBuild\BatchFile>msbuild Wrapper.proj /t:Demo /fl /nologo
Build started 5/18/2009 10:54:52 PM.
Project "C:\Data\Development\My Code\Community\MSBuild\BatchFile\Wrapper.proj" on node 0 (Demo target(s)).
Executing batch file test.bat
fromMSBuild:1
C:\Data\Development\My Code\Community\MSBuild\BatchFile\Wrapper.proj(17,5): error MSB3073: The command "test.bat FromMSBuild" exi
ted with code 101.
Done Building Project "C:\Data\Development\My Code\Community\MSBuild\BatchFile\Wrapper.proj" (Demo target(s)) -- FAILED.
Build FAILED.
"C:\Data\Development\My Code\Community\MSBuild\BatchFile\Wrapper.proj" (Demo target) (1) ->
(Demo target) ->
C:\Data\Development\My Code\Community\MSBuild\BatchFile\Wrapper.proj(17,5): error MSB3073: The command "test.bat FromMSBuild" e
xited with code 101.
0 Warning(s)
1 Error(s)
Time Elapsed 00:00:00.06
Sayed Ibrahim Hashimi
My Book: Inside the Microsoft Build Engine : Using MSBuild and Team Foundation Build
This question is a bit older, but the response may still be of interest, so here goes:
Slightly modify your MSBuild task to
<Exec Command='cmd.exe /C "call Batch.cmd params && exit %errorlevel%"' />
And keep the
exit /b %errorlevel%
in your Batch.cmd.
I haven't tried this, but what if you just set an environment variable named ERRORLEVEL? Hidden after the content of your Exec command, MSBuild has "exit %ERRORLEVEL%". %ERRORLEVEL% if set overrides any actual error level.