Ofline
What is MSBuild?
MSBuild (Microsoft Build Engine) is a build system and platform for building applications, primarily in the .NET ecosystem. It orchestrates how code is compiled, tested, packaged, and deployed by processing XML project files like .csproj, .fsproj and .vbproj. Visual Studio uses MSBuild, but you can use MSBuild without Visual Studio to build .NET applications.
Key Features of MSBuild
MSBuild processes an XML-based project file format which is configured to describe build items, configurations, and reusable build rules for consistency across projects.
There are different types of project files such as .csproj for C# projects, .fsproj for F# projects and .vbproj for visual basic projects.
Project File Structure
Lets create a dummy C# Web API project from scratch, without using dotnet new command to generate a template. Instead, we’ll manually create the required files, use the dotnet CLI to build and run the project, and test it using a simple HTTP request. Feel free to use your favorite editor to edit the files.

And that's all! You can play around .csproj configurations and explore other properties.
Learning Resources
Refer to the following resources if you would like to learn more about MSBuild and project files:
Читать далее...
MSBuild (Microsoft Build Engine) is a build system and platform for building applications, primarily in the .NET ecosystem. It orchestrates how code is compiled, tested, packaged, and deployed by processing XML project files like .csproj, .fsproj and .vbproj. Visual Studio uses MSBuild, but you can use MSBuild without Visual Studio to build .NET applications.
Key Features of MSBuild
- Project Building:
- Compiles your source code into Intermediate Language (IL) and packages it into binaries (.dll, .exe).
- Resolves project dependencies (e.g., NuGet packages) and includes them in the build process.
- Executes additional build tasks (e.g., running tests, creating packages, deployment tasks).
- XML-Based Configuration:
- Uses XML-based project files to define build instructions in a clear and extensible format.
- Project files are used to define build steps, configurations, dependencies, and more.
- Highly Customizable:
- You can write custom targets and tasks to extend its functionality.
- Integrated with .NET CLI:
- Commands like dotnet build, dotnet restore, and dotnet publish use MSBuild under the hood to build projects.
- Visual Studio has a built-in support for MSBuild. For editors that are not integrated with MSBuild like VS Code and Zed, the .NET CLI is commonly used to manage builds.
- Build Automation and CI/CD Integration:
- Integrates with CI/CD systems like GitHub Actions, Azure Pipelines, and Jenkins to automate builds, tests, and deployments.
- Defines build and deployment pipelines entirely in MSBuild scripts.
- Cross-Platform:
- Initially Windows-only, MSBuild became cross-platform starting with .NET Core, allowing builds on Linux and macOS.
- Ensures the same build logic works across operating systems, making it ideal for CI/CD pipelines.
MSBuild processes an XML-based project file format which is configured to describe build items, configurations, and reusable build rules for consistency across projects.
There are different types of project files such as .csproj for C# projects, .fsproj for F# projects and .vbproj for visual basic projects.
Project File Structure
File Root:
The project file begins with the <Project> root element which acts as the container for all other elements.
<Project>
</Project>
Modern .NET projects use SDK-style projects, where the SDK specifies a predefined set of build logic, properties, and imports.
Some available SDKs:
- Microsoft.NET.Sdk: For console apps or libraries.
- Microsoft.NET.Sdk.Web: For web projects lika Web APIs or MVC apps.
- Microsoft.NET.Sdk.Worker: For worker services and background jobs.
- Aspire.AppHost.Sdk: For Aspire app host.
- MSTest.Sdk: For MSTest apps.
Ways of declaring SDK:
Inline SDK declaration:
<Project Sdk="Microsoft.NET.Sdk">
</Project>
Using the <Sdk> element:
<Project>
<Sdk Name="Microsoft.NET.Sdk" />
</Project>
Properties:
- Key-value pairs used to configure builds and global settings like target framework, build configuration, and output paths.
They are defined within a <PropertyGroup>. Multiple <PropertyGroup> sections can be added.
<PropertyGroup>
<TargetFramework>net9.0</TargetFramework>
</PropertyGroup>
Conditions can be specified to dynamically enable properties:
<PropertyGroup Condition="'$(Configuration)' == 'Release'">
<Optimize>true</Optimize>
</PropertyGroup>
Examples on properties:
Target Framework
<TargetFramework> used to specify a single .NET version and <TargetFrameworks> for multiple versions:
<TargetFramework>net9.0</TargetFramework>
<TargetFrameworks>net9.0;net40;net45</TargetFrameworks>
Common TFMs: net9.0, net8.0, netstandard2.1, netcoreapp3.1, net481. OS-specific TFMs (e.g., net5.0-windows, net6.0-ios) include platform-specific bindings.
You can add to source code preprocessor directives for conditional compilation by framework:
#if NET40
Console.WriteLine("Target framework: .NET Framework 4.0");
#endif
Implicit using Directives
- Starting with .NET 6, C# projects automatically include commonly used namespaces via implicit global using directives, reducing the need to manually add them.
- Enabled by default for SDKs like Microsoft.NET.Sdk, Microsoft.NET.Sdk.Web, Microsoft.NET.Sdk.Worker, and Microsoft.NET.Sdk.WindowsDesktop.
<ImplicitUsings> is used to enable/disable the feature:
<PropertyGroup>
<ImplicitUsings>enable</ImplicitUsings>
</PropertyGroup>
Additional implicit global using directives can be specified by adding Using items to project file:
<ItemGroup>
<Using Include="System.IO.Pipes" />
</ItemGroup>
Compiler and Code Analyzer Warnings
- <TreatWarningsAsErrors>: Converts all compiler warnings into errors.
- <WarningsAsErrors>: Converts specific compiler warnings into errors.
- <CodeAnalysisTreatWarningsAsErrors>: Converts code analysis warnings into errors.
<NoWarn>: Suppresses specific warnings and doesn't show them in build outputs.
<PropertyGroup>
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
<WarningsAsErrors>CS0168</WarningsAsErrors>
<CodeAnalysisTreatWarningsAsErrors>true</CodeAnalysisTreatWarningsAsErrors>
<NoWarn>CS2002</NoWarn>
</PropertyGroup>
Items:
- Specify inputs to the build process, such as source files, packages, dependencies, and resources.
- They are defined within a <ItemGroup>. Multiple <ItemGroup> sections can be added.
For simplicity, use dotnet add package to add a package instead of manually adding it to the project file.
<ItemGroup>
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.6.2" />
<ProjectReference Include="..\OtherProject\OtherProject.csproj" />
<Compile Include="Program.cs" />
</ItemGroup>
Tasks:
- Individual steps within targets to perform certain actions.
MSBuild includes built-in tasks (e.g., Copy, Exec, MakeDir, Csc) and supports custom ones (by implementing ITask or deriving from the helper class Task)
<Target Name="CustomTarget">
<Exec Command="dotnet restore" />
<Copy SourceFiles="README.md" DestinationFolder="bin\docs\" />
<Csc Sources="@(Compile)" OutputAssembly="bin\MyApp.dll" />
</Target>
Targets:
- Group tasks and define sections of the project file as entry points for the build process.
BeforeTargets, AfterTargets and DependsOnTargets attributes can be used to order targets.
<Target Name="PreBuild" BeforeTargets="PreBuildEvent">
<Exec Command="echo pre build" />
</Target>
<Target Name="PostBuild" AfterTargets="PostBuildEvent">
<Exec Command="echo post build" />
</Target>
<Target Name="PostPostBuild" DependsOnTargets="PostBuild">
<Exec Command="echo post post build" />
</Target>
Lets create a dummy C# Web API project from scratch, without using dotnet new command to generate a template. Instead, we’ll manually create the required files, use the dotnet CLI to build and run the project, and test it using a simple HTTP request. Feel free to use your favorite editor to edit the files.
Create the project directory:
mkdir DemoApp
cd DemoApp
Create the .csproj file:
vim DemoApp.csproj
Add the following content to the .csproj file:
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>net9.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
</PropertyGroup>
</Project>
Create the Program.cs File:
vim Program.cs
Add the following content to Program.cs to define a simple /welcome API endpoint:
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
app.MapGet("/welcome", () => "Hello, you!");
app.Run();
Build the project - The output binaries will be placed in the bin/Debug/net9.0 directory by default.
dotnet build
Run the project - The output will indicate that the app is listening on: http://localhost:5000
dotnet run
Test the project - The output should be: Hello, you!.
curl http://localhost:5000/welcome
Final output via Zed editor:

And that's all! You can play around .csproj configurations and explore other properties.
Learning Resources
Refer to the following resources if you would like to learn more about MSBuild and project files:
- Microsoft Learn - .NET Project SDKs
- Microsoft Learn - MSBuild
- Microsoft Learn - MSBuild Properties
- Microsoft Learn - MSBuild Items
- Microsoft Learn - MSBuild Reference
Читать далее...