| MSBuild-5 :👈 | 👉:MSBuild-7 |
MSBuild Day 6 – Custom Props and Targets |
Today you will learn how to create custom .props and .targets files, how to reuse MSBuild logic across multiple projects, how MSBuild imports work, and how to safely override or extend behavior without modifying each project individually. This is essential for enterprise-level build automation.
MSBuild allows you to split logic into shared files:
Projects import these automatically when placed as:
Directory.Build.propsDirectory.Build.targetsUse it to share configuration values across many projects.
<Project>
<PropertyGroup>
<Company>MyCompany Ltd</Company>
<FileVersion>1.0.0</FileVersion>
<LangVersion>latest</LangVersion>
</PropertyGroup>
</Project>
Import it at the top of your project:
<Import Project="build\MyCompany.props" />
Or even better, import it automatically by placing it in:
/solution-root/build/MyCompany.props
Targets files contain actual build behavior. They are ideal for actions that should run for many projects.
<Project>
<Target Name="PrintCompany" BeforeTargets="Build">
<Message Text="Building for company: $(Company)" Importance="High" />
</Target>
<Target Name="CopyLicense" AfterTargets="Publish">
<Copy
SourceFiles="license.txt"
DestinationFolder="$(PublishDir)" />
</Target>
</Project>
Import it at the bottom of your project:
<Import Project="build\MyCompany.targets" />
These files allow you to apply logic to the entire solution automatically. No imports needed in project files.
<Project>
<PropertyGroup>
<MyGlobalSetting>Enabled</MyGlobalSetting>
</PropertyGroup>
</Project>
<Project>
<Target Name="AnnounceBuild" BeforeTargets="Build">
<Message Text="Starting build for $(MSBuildProjectName)" />
</Target>
</Project>
Every project in the folder inherits these automatically.
You can design a reusable MSBuild package with:
buildTransitive folder
mypackage.nuspec
build/
mylogic.targets
buildTransitive/
mylogic.targets
Place shared logic in buildTransitive to apply it to all projects that reference the NuGet package.
MSBuild allows safe extension using:
<Target Name="CustomStep" AfterTargets="Compile">
<Message Text="Running custom post-compile action..." />
</Target>
<Target Name="CoreCompile">
<Message Text="Custom compile override" />
</Target>
Warning: overriding a built-in target completely is risky.
Prefer using BeforeTargets or AfterTargets.
You can attach your logic to built-in pipelines like Build, Clean, and Publish.
<PropertyGroup>
<BuildDependsOn>
CustomPreStep;
$(BuildDependsOn)
</BuildDependsOn>
</PropertyGroup>
<Target Name="CustomPreStep">
<Message Text="Extra step before Build" />
</Target>
This inserts a new target into the default build chain.
<Project>
<Target Name="TagBuild" AfterTargets="Build">
<Message Text="Tagging build with timestamp: $([System.DateTime]::Now)" />
</Target>
</Project>
Directory.Build.targets
dotnet build
Every project prints the timestamp after building.
Tomorrow you will learn real-world build automation scenarios:
| MSBuild-5 :👈 | 👉:MSBuild-7 |