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 compilers
  • Microsoft.VisualStudio.Workload.NetCoreBuildTools — .NET SDK and .NET Core/5+ build support
  • Microsoft.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:

  • ConfigurationDebug or Release
  • PlatformAny CPU, x86, x64
  • OutputPath — Override the output directory: /p:OutputPath=C:buildoutput
  • AssemblyVersion — Override assembly version: /p:AssemblyVersion=2.0.0.0
  • TreatWarningsAsErrors — Fail the build on warnings: /p:TreatWarningsAsErrors=true
  • Deterministic — Produce deterministic output: /p:Deterministic=true
  • RestorePackages — 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 to dotnet restore for SDK-style projects)
  • Build — Compile the project
  • Clean — Delete all build outputs
  • Rebuild — Clean then Build
  • Publish — Compile and publish the project
  • Test — 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/.targets imports, 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.