MSBuild-5 :👈 👉:MSBuild-7

MSBuild Day 6 – Custom Props and Targets

Day 6 – Creating Custom Props/Targets and Reusable MSBuild Logic

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.

1. What Are .props and .targets Files?

MSBuild allows you to split logic into shared files:

  • .props – loaded early, for properties
  • .targets – loaded late, for targets and tasks

Projects import these automatically when placed as:

  • Directory.Build.props
  • Directory.Build.targets

2. Creating Your Own Props File

Use it to share configuration values across many projects.

Example: MyCompany.props

<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

3. Creating a Custom Targets File

Targets files contain actual build behavior. They are ideal for actions that should run for many projects.

Example: MyCompany.targets

<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" />

4. Using Directory.Build.props and Directory.Build.targets

These files allow you to apply logic to the entire solution automatically. No imports needed in project files.

Example: Directory.Build.props

<Project>
  <PropertyGroup>
    <MyGlobalSetting>Enabled</MyGlobalSetting>
  </PropertyGroup>
</Project>

Example: Directory.Build.targets

<Project>
  <Target Name="AnnounceBuild" BeforeTargets="Build">
    <Message Text="Starting build for $(MSBuildProjectName)" />
  </Target>
</Project>

Every project in the folder inherits these automatically.

5. Creating Reusable Build Logic for Many Projects

You can design a reusable MSBuild package with:

  • buildTransitive folder
  • NuGet packaging
  • Automatically applied props/targets

NuGet Structure:

mypackage.nuspec
build/
    mylogic.targets
buildTransitive/
    mylogic.targets

Place shared logic in buildTransitive to apply it to all projects that reference the NuGet package.

6. Overriding and Extending Existing Behavior

MSBuild allows safe extension using:

  • BeforeTargets
  • AfterTargets
  • DependsOnTargets

Extend without modifying original target:

<Target Name="CustomStep" AfterTargets="Compile">
    <Message Text="Running custom post-compile action..." />
</Target>

Override the contents of an existing target:

<Target Name="CoreCompile">
    <Message Text="Custom compile override" />
</Target>

Warning: overriding a built-in target completely is risky. Prefer using BeforeTargets or AfterTargets.

7. Build Hooks with DependsOnTargets

You can attach your logic to built-in pipelines like Build, Clean, and Publish.

Example:

<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.

8. Hands-On Exercise (15 minutes)

Step 1 — Create a shared targets file

<Project>
  <Target Name="TagBuild" AfterTargets="Build">
    <Message Text="Tagging build with timestamp: $([System.DateTime]::Now)" />
  </Target>
</Project>

Step 2 — Place it in solution root:

Directory.Build.targets

Step 3 — Run

dotnet build

Every project prints the timestamp after building.

9. Summary

  • .props defines shared properties.
  • .targets defines shared build actions.
  • Directory.Build files apply automatically to all projects.
  • NuGet packages can distribute MSBuild logic.
  • BeforeTargets/AfterTargets safely extend behavior.
  • DependsOnTargets modifies build pipeline order.

10. Day 7 Preview

Tomorrow you will learn real-world build automation scenarios:

  • Versioning (Git + MSBuild)
  • Environment-based configuration
  • DevOps pipeline integration
  • MAUI build customizations
  • File generation and pre-compile logic
Back to Index
MSBuild-5 :👈 👉:MSBuild-7
*