Understanding Tasks and Creating Targets
MSBuild has the concept of a
task, which is simply a unit of work that can be executed during the
build process. You can add both predefined and custom tasks to the build
process inside the project file. (Most built-in tasks are
self-explanatory, and if you use Visual Studio to create the project
file, IntelliSense can be helpful as usual.) Tasks are specified within Target elements. A target is basically a container for tasks, and you can execute tasks by referring the enclosing Target element. For example, the following task sends a message to the specified output log (which is the Console window by default):
<Target Name="SendMessage">
<Message Importance="high"
Text="This is a custom message to demonstrate tasks"/>
</Target>
The important thing is assigning the Name property so that you can later refer to target. To execute a task in the build process, you need to run MSBuild by supplying a /target: switch (or simply /t:) and passing the target name as in the following example:
MsBuild MsBuildTest.vbproj /target:SendMessage
Figure 2 shows how the message appears in the log.
You can also execute multiple
targets in a single command line by separating their names with a
semicolon. With tasks you can execute also external applications that
can influence the build process. The following code demonstrates how to
accomplish this:
<Target Name="ExecuteMyCustomTool">
<Exec Command="MyExternalFile.exe" ContinueOnError="false"
WorkingDirectory="C:\MyAppsFolder"/>
</Target>
The Exec built-in task enables running the external application to be executed specified with the Command property and that resides in the WorkingDirectory path. You can also set if the build process must break in case the external application returns an error code (ContinueOnError).
MSBuild is a managed application taking advantage of Microsoft.Build.Framework.dll assembly and of the Microsoft.Build.Framework namespace. They also expose types for writing code against MSBuild, such as the ILogger and ITask interfaces.
|
Inside target definitions you can also refer to properties defined inside PropertyGroup
nodes. The following code demonstrates how you can create a directory
during the build process by assigning to the new directory the name of a
folder previously defined within properties:
<Target Name="CreateDataDir">
<MakeDir Directories="$(MyDataDirectory)"/>
</Target>
To add a reference to a property value, you use the $
symbol followed by the name of the property enclosed within
parentheses. Now consider the following sample project that invokes the
Visual Basic compiler to build multiple code files into one executable:
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" DefaultTargets="Compile"
xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<!–– Defines a series of custom items
pointing to VB code files ––>
<ItemGroup>
<VBFile Include="File1.vb"/>
<VBFile Include="File2.vb"/>
</ItemGroup>
<!–– Defines a property storing the
output exe name––>
<PropertyGroup>
<AssemblyName>MyApp.exe</AssemblyName>
</PropertyGroup>
<!–– Creates a new target––>
<Target Name = "Compile">
<Vbc
Sources = "@(VBFile)"
OutputAssembly = "$(AssemblyName)">
<Output
TaskParameter = "OutputAssembly"
ItemName = "EXEFile" />
</Vbc>
</Target>
</Project>
Vbc is a predefined
tag that tells MSBuild to run the Visual Basic command-line compiler
against the specified set of files. By mixing the preceding code with
concepts previously discussed, it should be clearer how you could run an
external tool instead of a .NET compiler, such as a documentation
compiler, against a set of desired files and to let MSBuild pass all
information to the external tool and build the final file.