Introduction: MSBuild as a Build Server on Windows Server 2022
MSBuild (Microsoft Build Engine) is the core build platform for .NET and Windows applications. It processes XML-based project files (.csproj, .vbproj, .sln) and executes a directed acyclic graph of build tasks: compiling code, resolving NuGet packages, running tests, publishing artifacts, and more. On Windows Server 2022, setting up a dedicated MSBuild server is the foundation for building .NET Framework, .NET Core, .NET 8+, ASP.NET, WPF, WinForms, and mixed-mode C++ projects in a repeatable, automated fashion. This guide covers installing MSBuild without a full Visual Studio installation, using MSBuild from the command line, key properties and targets, binary logging, NuGet restore, Docker image builds, and CI/CD integration.
Installing MSBuild via Visual Studio Build Tools
MSBuild is delivered as part of Visual Studio and Visual Studio Build Tools. For a server with no UI, install Visual Studio Build Tools — a lightweight installer that provides MSBuild and build workloads without the full Visual Studio IDE. Download the Build Tools installer from:
https://visualstudio.microsoft.com/downloads/#build-tools-for-visual-studio-2022
For unattended installation from the command line (ideal for server provisioning scripts), run the installer with specific workload flags:
vs_BuildTools.exe --quiet --wait --norestart ^
--add Microsoft.VisualStudio.Workload.MSBuildTools ^
--add Microsoft.VisualStudio.Workload.NetCoreBuildTools ^
--add Microsoft.VisualStudio.Workload.WebBuildTools ^
--add Microsoft.VisualStudio.Component.NuGet ^
--add Microsoft.VisualStudio.Component.Windows11SDK.22621
Key workload IDs:
Microsoft.VisualStudio.Workload.MSBuildTools— Core MSBuild tools and .NET Framework compilersMicrosoft.VisualStudio.Workload.NetCoreBuildTools— .NET SDK and .NET Core/5+ build supportMicrosoft.VisualStudio.Workload.WebBuildTools— ASP.NET and web project build support
After installation, MSBuild is located at:
C:Program Files (x86)Microsoft Visual Studio2022BuildToolsMSBuildCurrentBinMSBuild.exe
Add it to the system PATH or use the Developer Command Prompt for VS 2022 Build Tools, which sets all required environment variables automatically. To add to PATH via PowerShell:
$msbuildPath = "C:Program Files (x86)Microsoft Visual Studio2022BuildToolsMSBuildCurrentBin"
$currentPath = [Environment]::GetEnvironmentVariable("Path", [EnvironmentVariableTarget]::Machine)
[Environment]::SetEnvironmentVariable("Path", "$currentPath;$msbuildPath", [EnvironmentVariableTarget]::Machine)
Basic MSBuild Command-Line Usage
The fundamental MSBuild invocation compiles a project:
MSBuild.exe MyProject.csproj
Specify a target with /t: and a configuration property with /p::
MSBuild.exe MyProject.csproj /t:Build /p:Configuration=Release /p:Platform=x64
Build a .sln solution file in Release mode:
MSBuild.exe MySolution.sln /t:Build /p:Configuration=Release /p:Platform="Any CPU"
Clean build artifacts:
MSBuild.exe MySolution.sln /t:Clean
Clean then rebuild in one command:
MSBuild.exe MySolution.sln /t:Clean;Build /p:Configuration=Release
Publish an ASP.NET project to a local folder:
MSBuild.exe MyWebApp.csproj /t:Publish /p:Configuration=Release /p:PublishUrl=C:publishedmywebapp /p:DeployOnBuild=true
Common MSBuild Properties
MSBuild properties control the behavior of the build. They are passed with /p:PropertyName=Value. The most commonly used are:
Configuration—DebugorReleasePlatform—Any CPU,x86,x64OutputPath— Override the output directory:/p:OutputPath=C:buildoutputAssemblyVersion— Override assembly version:/p:AssemblyVersion=2.0.0.0TreatWarningsAsErrors— Fail the build on warnings:/p:TreatWarningsAsErrors=trueDeterministic— Produce deterministic output:/p:Deterministic=trueRestorePackages— Trigger NuGet restore during build:/p:RestorePackages=true
Common MSBuild Targets
Targets define the actions MSBuild performs. Key built-in targets include:
Restore— Restore NuGet packages (equivalent todotnet restorefor SDK-style projects)Build— Compile the projectClean— Delete all build outputsRebuild— Clean then BuildPublish— Compile and publish the projectTest— Run unit tests (requires test runner integration)Pack— Create a NuGet package from the project
MSBuild Logging Verbosity
MSBuild logging is controlled with the /verbosity: flag (abbreviated /v:). Options in increasing detail are: quiet, minimal, normal, detailed, diagnostic.
# Minimal output - only errors and warnings
MSBuild.exe MySolution.sln /t:Build /p:Configuration=Release /v:minimal
# Detailed output for debugging build issues
MSBuild.exe MySolution.sln /t:Build /p:Configuration=Release /v:detailed
# Diagnostic - maximum detail, useful for investigating property and target resolution
MSBuild.exe MySolution.sln /t:Build /p:Configuration=Release /v:diagnostic 2>&1 | Out-File build_diagnostic.log
Write log output to a file using /filelogger (abbreviated /fl):
MSBuild.exe MySolution.sln /t:Build /p:Configuration=Release /fl /flp:LogFile=build.log;Verbosity=detailed
MSBuild Binary Log (binlog)
The binary log (.binlog) is the most powerful MSBuild logging feature. It captures the complete build event stream in a compact binary format that can be replayed and analyzed with the MSBuild Structured Log Viewer (MSBuildLog.exe). Binary logs are invaluable for diagnosing complex build failures in CI/CD environments:
MSBuild.exe MySolution.sln /t:Build /p:Configuration=Release /bl:build.binlog
Download the Structured Log Viewer from https://msbuildlog.com/ and open the .binlog file to browse target timings, property values, task inputs/outputs, and errors in a tree view. You can also analyze binary logs programmatically:
dotnet tool install -g dotnet-msbuild-binlog-search
msbuild-binlog-search build.binlog --search "error"
NuGet Restore in MSBuild
For SDK-style projects (<Project Sdk="Microsoft.NET.Sdk">), MSBuild can restore NuGet packages as part of the build using the Restore target. Always run restore before build:
MSBuild.exe MySolution.sln /t:Restore
MSBuild.exe MySolution.sln /t:Build /p:Configuration=Release
Or combine into a single invocation:
MSBuild.exe MySolution.sln /t:Restore;Build /p:Configuration=Release
For non-SDK (legacy) projects, use the NuGet CLI for restore:
nuget.exe restore MySolution.sln -NonInteractive
MSBuild.exe MySolution.sln /t:Build /p:Configuration=Release
Configure a private NuGet feed in nuget.config at the solution root:
Building Docker Images from MSBuild
MSBuild can invoke Docker as part of the build pipeline. The Microsoft.NET.Sdk.Web SDK includes built-in Docker publish support. To publish a containerized ASP.NET app and push it to a registry:
MSBuild.exe MyWebApp.csproj ^
/t:Publish ^
/p:Configuration=Release ^
/p:PublishProfile=DefaultContainer ^
/p:ContainerImageName=myapp ^
/p:ContainerImageTag=1.0.0 ^
/p:ContainerRegistry=myacr.azurecr.io
This uses the .NET SDK container publishing feature (available in .NET 7+). For traditional Dockerfile-based builds, call Docker as a MSBuild Exec task or run it as a post-build step:
MSBuild.exe MySolution.sln /t:Build /p:Configuration=Release
docker build -t myapp:latest -f Dockerfile .
docker push myregistry.azurecr.io/myapp:latest
MSBuild vs dotnet build
dotnet build is the CLI front end for MSBuild that ships with the .NET SDK. For SDK-style projects, it is functionally equivalent to calling MSBuild directly and is the preferred command. However, MSBuild.exe from Visual Studio Build Tools is still required for:
- Legacy .NET Framework projects (non-SDK style
.csproj) - Solution files that mix SDK and non-SDK projects
- MSBuild-specific features like custom targets,
.props/.targetsimports, and fine-grained property injection - WPF, WinForms, and Windows-specific workloads on the full .NET Framework
For .NET 6+/8+ SDK-style projects, dotnet build is simpler and cross-platform:
dotnet restore MySolution.sln
dotnet build MySolution.sln -c Release --no-restore
dotnet publish MyWebApp.csproj -c Release -o ./publish --no-build
Integrating MSBuild with Jenkins
On a Windows Server 2022 Jenkins agent, add MSBuild to PATH and invoke it from a Freestyle Job or Pipeline. A Jenkinsfile example:
pipeline {
agent { label 'windows-server-2022' }
stages {
stage('Restore') {
steps {
bat 'MSBuild.exe MySolution.sln /t:Restore /v:minimal'
}
}
stage('Build') {
steps {
bat 'MSBuild.exe MySolution.sln /t:Build /p:Configuration=Release /p:Platform="Any CPU" /v:minimal /bl:build.binlog'
}
}
stage('Publish') {
steps {
bat 'MSBuild.exe MyWebApp.csproj /t:Publish /p:Configuration=Release /p:PublishUrl=C:\artifacts\mywebapp /v:minimal'
}
}
}
post {
always {
archiveArtifacts artifacts: 'build.binlog', allowEmptyArchive: true
}
}
}
Integrating MSBuild with GitHub Actions
A GitHub Actions workflow using a Windows Server 2022 self-hosted runner or the hosted windows-2022 runner:
name: Build
on:
push:
branches: [main]
jobs:
build:
runs-on: windows-2022
steps:
- uses: actions/checkout@v4
- name: Setup MSBuild
uses: microsoft/setup-msbuild@v2
- name: Restore NuGet packages
run: msbuild MySolution.sln /t:Restore /v:minimal
- name: Build Solution
run: msbuild MySolution.sln /t:Build /p:Configuration=Release /p:Platform="Any CPU" /v:minimal /bl:build.binlog
- name: Upload binary log
uses: actions/upload-artifact@v4
if: always()
with:
name: binlog
path: build.binlog
Summary
Windows Server 2022 is an excellent platform for a dedicated MSBuild build server. Visual Studio Build Tools provides a lightweight, scriptable installation that delivers MSBuild and all required workloads without the overhead of a full IDE. The command-line interface is rich and composable: targets, properties, logging verbosity, file loggers, and binary logs give complete control and visibility over every build. NuGet restore, Docker image publishing, and integration with Jenkins and GitHub Actions make MSBuild the authoritative build engine for Windows-based .NET CI/CD pipelines.