Output from Exec task resulting in build failure

[Notice: This blog is based on Visual Studio 2010 SP1]

One of our customers sometime back came to us with a strange issue. They were facing the following error as shown in below screenshot…

The source of the error was from an MSBuild task they had. This is how the task looks…
<snip>…  <Target Name="SomeTask" AfterTargets="Build">   <Exec Command="echo Error:"/>  </Target> </Project>

The command for the task is one simple command “echo Error:”, please note I modified the command to make it look simple. In the customer’s task they had a 3rd party tool which emitted a text similar to what I’m emitting via ‘echo’ command.

Initially we spent a long time trying to understand what is going wrong. Eventually an MSDN blog enlightened me (Thanks!). 

blogs.msdn.com/b/msbuild/archive/2006/11/03/msbuild-visual-studio-aware-error-messages-and-message-formats.aspx

So the gist of the whole issue was ‘MSBuild/Visual Studio aware error messages’. We only need to follow a particular format for MSBuild/Visual Studio to recognize the text being output  as an error message. In this case the 3rd party tool inadvertently was
following the rule.

MFC programmers know that we used to emit trace messages for some error conditions in our code into the debugger output window using AfxTrace, TRACE, OutputDebugString etc. If we follow a particular format for these messages then we can double click on these messages and visual studio will take us to the line of code. See a small sample…

 // Disclaimer: Do not use this piece of code, its not tested. :)
#define MY_TRACE(Err) TCHAR Buf[MAX_PATH*2];\
 _stprintf_s(Buf, _T("%s(%d): %s\n"), _T(__FILE__), __LINE__, Err);\
 OutputDebugString(Buf);
 
 // Call likewise
 MY_TRACE(_T("Some stuff happened"));

This will emit following line of code:
c:\projects\testing\testing\testing.cpp(14): Some stuff happened

Double click on the line and visual studio will take you to Testing.cpp line number 14.

In our customer’s case MSBuild considered the output as an error because the 3rd party emitted code in an understandable format for MSBuild. So the question is how to get rid of this error. There are two steps..

  1. One way to fix the issue is to redirect the output to NUL or to another file but not recommended.
  2. A more proper way to do this is via the IgnoreStandardErrorWarningFormat attribute to the Exec tag. See below example

 <snip>…  <Target Name="SomeTask" AfterTargets="Build">   <Exec Command="echo Error:" IgnoreStandardErrorWarningFormat="true"></Exec>  </Target> </Project>
This is the output we get…

1>------ Rebuild All started:
Project: Testing, Configuration: Debug Win32 ------
1> stdafx.cpp
1> Testing.cpp
1> Testing.vcxproj -> c:\Projects\Testing\Debug\Testing.exe
1> Error:
========== Rebuild All: 1 succeeded, 0 failed, 0 skipped ==========

Yep now we get to build without errors. We can have multiple Exec commands which does/does not ignore the error. So if you have tool which should stop a build, if there is an error in the tool, then you can use this feature of MSBuild. Let me demonstrate with an example…<Snip>... <Target Name="SomeTask" AfterTargets="Build">   <Exec Command="echo Error:" IgnoreStandardErrorWarningFormat="true"></Exec>   <Exec Command="echo Error: Critical error"></Exec> </Target> </Project>
Please note that in the second Exec task we purposely removed IgnoreStandardErrorWarningFormat attribute. We wanted the build to fail because it is a critical error.

If you are not aware of such a feature of MSBuild you could end up losing hair. :) So be aware and make use of this feature.