msbuild file.csproj /t:TargetA # execute TargetA in file.csproj msbuild file.sln # build all projects in sln msbuild file.csproj /v:diag # specify verbosity
Properties are key/values pairs used to configure builds. A property value can be changed by re-defining the property.
<PropertyGroup> <Prop1>PropValue</Prop1> <Prop2 Condition=" '$(Prop2)' == '' ">NewValue</Prop2> </PropertyGroup>
Items are inputs into the build system. 'MyItem' is the item type (or item name).
<ItemGroup> <MyItem Include="file1.txt" /> <MyItem Include="file2.txt" /> </ItemGroup>
Tasks are units of executable code. The logic of a task is mapped to MSBuild with the <UsingTask> element.
<PropertyGroup> <Dir>MyDirectory</Dir> </PropertyGroup> <Target Name="MyTargetCreateDir"> <MakeDir Directories="$(Dir)" /> </Target>
Targets group tasks together in a particular order and expose sections of a proj file as entry points.
<ItemGroup> <File>File1.cs</File> <File>File2.cs</File> <File>File3.cs</File> </ItemGroup> <Target Name="MyTargetCompile"> <Csc Sources="@(File)" /> </Target>
Creating properties - Properties outside of Target are assigned during the evaluation phase of a build. During the execution phase, properties can be created or modified as follows:
Element | Reference | Remarks |
---|---|---|
Property | $(PropName) | - used to pass values to tasks - used to evaluate conditions - used to store values in a proj file |
Environment Variable | $(Path) or $(PATH) | - property names are not case sensitive - values of environment variables are set at the beginning of a build and are not modified |
Items | @(ItemType) | - a parameter for a task - the task uses individual items |
Case-sensitive | Not case-sensitive |
---|---|
- Element Name - Attribute Name | - Property Name - Item Type - Metadata Name |
Example: Specify a DefaultTarget:
<Project DefaultTargets="MainTarget" Sdk="Microsoft.NET.Sdk"> <Target Name="MainTarget"> ... </Target> </Project>
Example: .NET Core app:
<PropertyGroup> <OutputType>Exe</OutputType> <TargetFramework>netcoreapp2.0</TargetFramework> </PropertyGroup>
Example: Include files and references:
<ItemGroup> <Compile Include="**\*.cs" /> <EmbeddedResources Include="**\*.resx /> </ItemGroup> <ItemGroup> <PackageReference Include="Microsoft.NETCore.App" Version="1.0.1" /> </ItemGroup>
Example: Default property values:
<PropertyGroup> <RestoreSuccess Condition=" '$(RestoreSuccess)' == '' ">True</RestoreSuccess> <RestoreTool Condition=" '$(RestoreTool)' == '' ">NuGet</RestoreTool> <NuGetPackageRoot Condition=" '$(NuGetPackageRoot)' == '' ">$(UserProfile)\.nuget\packages\</NuGetPackageRoot> <NuGetProjectStyle Condition=" '$(NuGetProjectStyle)' == '' ">PackageReference</NuGetProjectStyle> <NuGetToolVersion Condition=" '$(NuGetToolVersion)' == '' ">4.7.0</NuGetToolVersion> </PropertyGroup>
Example: Import another MSBuild script if it exists:
<ImportGroup> <Import Project="C:\MyProject\Script.props" Condition="Exists('C:\MyProject\Script.props')" /> </ImportGroup>
Example: Store XML in a property:
<PropertyGroup> <MyProp> ... XML goes here; it may contain other $props </MyProp> </PropertyGroup>
Example: Use a condition comparing to a bool value 'DoSomething' and another condition comparing to a string value 'SayHello':
<Project DefaultTargets="MainTarget" Sdk="Microsoft.NET.Sdk"> <PropertyGroup> <OutputType>Exe</OutputType> <TargetFramework>netcoreapp2.0</TargetFramework> </PropertyGroup> <PropertyGroup> <DoSomething>true</DoSomething> <SayHello>hello</SayHello> </PropertyGroup> <Target Name="MainTarget"> <CallTarget Targets="TestBool;TestStr" /> </Target> <Target Name="TestBool" Condition="$(DoSomething)"> <Message Text="Something" /> </Target> <Target Name="TestStr" Condition="$(SayHello) == 'hello'"> <Message Text="Hello" /> </Target> </Project>
Example: Display the names and the ModifiedTime attribute of files located in a specified folder. In this example, we assume there are three files d1.dat, d2.dat, and d3.dat in a subfolder 'data':
<Project DefaultTargets="ListDataFiles" Sdk="Microsoft.NET.Sdk"> <PropertyGroup> <OutputType>Exe</OutputType> <TargetFramework>netcoreapp2.0</TargetFramework> <DataPath>$(MSBuildProjectDirectory)\data\*.dat</DataPath> </PropertyGroup> <ItemGroup> <DataFiles Include="$(DataPath)" /> </ItemGroup> <Target Name="ListDataFiles"> <Message Text="@(DataFiles)" /> <Message Text="@(DataFiles->'%(ModifiedTime)')" /> </Target> </Project>
Output:
Project "C:\Temp\test.csproj" on node 1 (default targets). ListDataFiles: C:\Temp\data\d1.dat;C:\Temp\data\d2.dat;C:\Temp\data\d3.dat 2018-08-07 13:43:00.6470153;2018-08-07 13:43:00.6470153;2018-08-07 13:43:00.6470153
Example: Display values of an item's custom property 'Description':
<Project DefaultTargets="ListDescriptions" Sdk="Microsoft.NET.Sdk"> <PropertyGroup> <OutputType>Exe</OutputType> <TargetFramework>netcoreapp2.0</TargetFramework> </PropertyGroup> <ItemGroup> <Mammals Include="Echidna"> <Description>Echidna description</Description> </Mammals> <Mammals Include="Pangolin"> <Description>Pangolin description</Description> </Mammals> <Mammals Include="Porpoise"> <Description>Porpoise description</Description> </Mammals> </ItemGroup> <Target Name="ListDescriptions"> <Message Text="@(Mammals)" /> <Message Text="@(Mammals->'%(Description)')" /> </Target> </Project>
Output:
Project "C:\Temp\test.csproj" on node 1 (default targets). ListDescriptions: Echidna;Pangolin;Porpoise Echidna description;Pangolin description;Porpoise description
Example: Use AfterTargets to enforce the order of targets' execution:
<Project DefaultTargets="MainTarget" Sdk="Microsoft.NET.Sdk"> <PropertyGroup> <OutputType>Exe</OutputType> <TargetFramework>netcoreapp2.0</TargetFramework> </PropertyGroup> <Target Name="MainTarget"> <CallTarget Targets="TargetZ" /> </Target> <Target Name="TargetX" AfterTargets="TargetZ"> <Message Text="X" /> </Target> <Target Name="TargetY" AfterTargets="TargetZ"> <Message Text="Y" /> </Target> <Target Name="TargetZ"> <Message Text="Z" /> </Target> </Project>
Output:
Project "C:\Temp\test.csproj" on node 1 (default targets). TargetZ: Z TargetX: X TargetY: Y
Example: Use DependsOnTargets to enforce the order of targets' execution. Note that C is executed only once:
<Project DefaultTargets="MainTarget" Sdk="Microsoft.NET.Sdk"> <PropertyGroup> <OutputType>Exe</OutputType> <TargetFramework>netcoreapp2.0</TargetFramework> </PropertyGroup> <Target Name="MainTarget"> <CallTarget Targets="TargetA" /> </Target> <Target Name="TargetA" DependsOnTargets="TargetC"> <Message Text="A" /> <CallTarget Targets="TargetB" /> </Target> <Target Name="TargetB" DependsOnTargets="TargetC"> <Message Text="B" /> </Target> <Target Name="TargetC"> <Message Text="C" /> </Target> </Project>
Output:
Project "C:\Temp\test.csproj" on node 1 (default targets). TargetC: C TargetA: A TargetB: B
Example: Include targets and properties from separate *.props files:
<Project DefaultTargets="MainTarget" Sdk="Microsoft.NET.Sdk"> <Import Project="Common.targets" /> <Import Project="Common.props" /> <Target Name="MainTarget" DependsOnTargets="TargetA"> <Message Text="Hello, $(FullName)" /> </Target> </Project>
<Project> <!-- Shared targets --> <Target Name="TargetA"> <Message Text="A" /> </Target> <Target Name="TargetB"> <Message Text="B" /> </Target> <Target Name="TargetC"> <Message Text="C" /> </Target> </Project>
<Project> <!-- Shared properties --> <PropertyGroup> <OutputType>Exe</OutputType> <TargetFramework>netcoreapp2.0</TargetFramework> <First>Leon</First> <Last>McPowell</Last> <FullName>$(First) $(Last)</FullName> </PropertyGroup> </Project>
Output:
Project "C:\Temp\test.csproj" on node 1 (default targets). TargetA: A MainTarget: Hello, Leon McPowell
Example: Compress files using the MSBuild.ExtensionPack.Compression.DNZip task from MSBuild.Extension.Pack. You need to download the extension pack files (dlls) first and point MSBuild to their location (here: a 'tools' subfolder):
<Project DefaultTargets="ZipFilesTarget" Sdk="Microsoft.NET.Sdk"> <PropertyGroup> <OutputType>Exe</OutputType> <TargetFramework>netcoreapp2.0</TargetFramework> </PropertyGroup> <Import Project="MSBuild.Extension.Pack.targets" /> <Target Name="ZipFilesTarget"> <ItemGroup> <FilesToZip Include="data\*.*" /> </ItemGroup> <MSBuild.ExtensionPack.Compression.DNZip TaskAction="Create" CompressFiles="@(FilesToZip)" ZipFileName="files.zip" /> </Target> </Project>
The MSBuild.Extension.Pack.targets file generated automatically:
<?xml version="1.0" encoding="utf-8"?> <Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> <PropertyGroup> <ExtensionTasksPath>tools\</ExtensionTasksPath> </PropertyGroup> ... <!-- ============== Framework ============== --> <UsingTask AssemblyFile="$(ExtensionTasksPath)MSBuild.ExtensionPack.dll" TaskName="MSBuild.ExtensionPack.CodeQuality.FxCop"/> <UsingTask AssemblyFile="$(ExtensionTasksPath)MSBuild.ExtensionPack.dll" TaskName="MSBuild.ExtensionPack.CodeQuality.NUnit"/> <UsingTask AssemblyFile="$(ExtensionTasksPath)MSBuild.ExtensionPack.dll" TaskName="MSBuild.ExtensionPack.CodeQuality.NUnit3"/> <UsingTask AssemblyFile="$(ExtensionTasksPath)MSBuild.ExtensionPack.dll" TaskName="MSBuild.ExtensionPack.Communication.Email"/> <UsingTask AssemblyFile="$(ExtensionTasksPath)MSBuild.ExtensionPack.dll" TaskName="MSBuild.ExtensionPack.Communication.Ftp"/> <UsingTask AssemblyFile="$(ExtensionTasksPath)MSBuild.ExtensionPack.dll" TaskName="MSBuild.ExtensionPack.Communication.MSMQ"/> <UsingTask AssemblyFile="$(ExtensionTasksPath)MSBuild.ExtensionPack.dll" TaskName="MSBuild.ExtensionPack.Compression.Cab"/> <UsingTask AssemblyFile="$(ExtensionTasksPath)MSBuild.ExtensionPack.dll" TaskName="MSBuild.ExtensionPack.Compression.DNZip"/> <UsingTask AssemblyFile="$(ExtensionTasksPath)MSBuild.ExtensionPack.dll" TaskName="MSBuild.ExtensionPack.Compression.Zip"/> <UsingTask AssemblyFile="$(ExtensionTasksPath)MSBuild.ExtensionPack.dll" TaskName="MSBuild.ExtensionPack.Computer.ActiveDirectory"/> <UsingTask AssemblyFile="$(ExtensionTasksPath)MSBuild.ExtensionPack.dll" TaskName="MSBuild.ExtensionPack.Computer.ComponentServices"/> <UsingTask AssemblyFile="$(ExtensionTasksPath)MSBuild.ExtensionPack.dll" TaskName="MSBuild.ExtensionPack.Computer.EnvironmentVariable"/> <UsingTask AssemblyFile="$(ExtensionTasksPath)MSBuild.ExtensionPack.dll" TaskName="MSBuild.ExtensionPack.Computer.EventLog"/> ... </Project>
Output:
Project "C:\Temp\test.csproj" on node 1 (default targets). ZipFilesTarget: Creating ZipFile: files.zip
Example: Remove an output folder and build a VS solution:
<Project DefaultTargets="BuildSolution" Sdk="Microsoft.NET.Sdk"> <PropertyGroup> <OutputType>Exe</OutputType> <TargetFramework>netcoreapp2.0</TargetFramework> <OutputPath>$(MSBuildThisFileDirectory)Output</OutputPath> <SolutionFileName>C:\Projects\DoSomething.sln</SolutionFileName> </PropertyGroup> <Target Name="CleanDir"> <RemoveDir Directories="$(OutputPath)" Condition="Exists($(OutputPath))" /> </Target> <Target Name="BuildSolution" DependsOnTargets="CleanDir"> <MSBuild Projects="$(SolutionFileName)" Properties="Configuration=Release;OutputPath=$(OutputPath)" /> </Target> </Project>