MSBuild is a really interesting beast! He who has not used it haven’t encountered its quirks!
Should I care about MSBuild?
If you are working on a .NET stuff, you definitely should know how it works, because the whole .NET ecosystem is built around it. From your project files (e.g. csproj
) all the way down to all Microsoft targets
. Varying from what should go to the intermediate (obj
) dir and what to the output (bin
), copying references (if needed) or even publishing a self-contained executable (if using .NET Core).
Basically, there is not way around it! Love it or hate it - you are going to use it.
MSBuild 101
Before continuing, you should familiarize yourself with 2 core concepts:
Those are the 3 building blocks of MSBuild.
If you don’t want to dig in, just remember this:
- Properties are used for a single value (e.g. path to a config file).
- Items (or items groups) are used for multiple values (e.g. list of all project files).
- Tasks do the actual work (executing commands, copying stuff, etc).
Execute an external command
Executing an external command in MSBuild is pretty easy, we need to just use the exec
task like so:
<Exec Command="echo foobar" />
Pretty simple and of course - pretty useless!
Check the exit code
In a lot of scenarios you want to check the exit code:
<Exec Command="myecho foobar"
ContinueOnError="true">
<Output TaskParameter="ExitCode" PropertyName="MyEchoExitCode"/>
</Exec>
This will set the MyEchoExitCode
property to 127
if running on MacOS and 9009
if running on Windows for command not found (unless you have myecho
executable in your PATH
).
Note the ContinueOnError
part - if omitted the script will fail and the execution will stop. You can think of it as a try
/catch
block!
* You can check more options for the exec task.
Act accordingly
Having captured the exit code was the hard part! Now comes the easy part - doing stuff with the result you’ve got.
Having repeatable build process is a MUST, but you can spice it up with the following snippet:
<PropertyGroup>
<IsBlueMoon Condition=" '$([System.DateTime]::Now.ToString(ss))' == '59' " >true</IsBlueMoon>
</PropertyGroup>
<Exec Command="build my.project"
ContinueOnError="true">
<Output TaskParameter="ExitCode" PropertyName="BuildExitCode"/>
</Exec>
<Error Message="BUILD FAILED!" Condition=" '$(BuildExitCode)' != '0' AND '$(IsBlueMoon)' != 'true' ">
This way your build won’t fail when there is a blue moon outside!
Final words
That was a basic example of how you can use MSBuild to execute a custom command and check the exit code.
Next time, we’re going to leverage this to actually do some useful stuff! ;)