Visual Studio Solution: Only One Project Published in Build Pipeline

Abstract: Resolve the issue where Azure DevOps builds only publish the startup project by configuring MSBuild arguments or using dotnet publish for all solution projects.

Created: 2026-08-28 by

When Azure DevOps builds a Visual Studio solution, only the startup or web project publishes by default because MSBuild targets specific entry points. To publish all projects, you must explicitly configure the build task to use /p:DeployOnBuild=true combined with /p:PublishProfile=YourProfile for each target, or switch to a dedicated Publish step that iterates through the solution items.

Understanding the Default Build Behavior

In a typical .NET solution containing multiple projects, such as a Web API and several class libraries, the build process is designed to compile code rather than deploy artifacts. When you add a standard "Visual Studio Build" task in an Azure DevOps pipeline, it invokes msbuild.exe on your .sln file. By default, MSBuild compiles every project referenced in the solution to produce assembly files (DLLs) in the bin directory. However, compilation is not the same as publishing. Publishing involves creating a self-contained folder structure or a zip package ready for deployment to a server, App Service, or container registry. Most developers encounter this issue when they expect the output artifact to contain all compiled binaries, but only find the files from one project, usually the main web application. This happens because the build task does not automatically trigger the publish workflow for non-web projects unless explicitly instructed. The pipeline succeeds because the compilation succeeded, but the deployment preparation fails silently for the other projects. Understanding this distinction is crucial before applying fixes.

Configuring MSBuild Arguments Correctly

The most common approach to fixing this is modifying the arguments passed to the MSBuild task. Many guides suggest using /p:DeployOnBuild=true, which is correct but incomplete. If you only use this flag, MSBuild will attempt to publish the project that has a default publish profile or is marked as the startup project. It will ignore libraries and worker services. To force publication of specific projects, you need to combine parameters carefully. You should update your pipeline YAML or classic editor configuration to include the following arguments in the MSBuild task:
/p:DeployOnBuild=true
/p:PublishProfile=FolderProfile
/p:PackageLocation=$(build.artifactStagingDirectory)
However, note that PublishProfile expects a single profile name. If your solution has different publish profiles for different projects, this single argument will fail or apply only to the first match. A more robust method involves ensuring that each project you wish to publish has a corresponding publish profile defined in Visual Studio. You can create these by right-clicking the project in Solution Explorer, selecting "Publish," and choosing "Folder." Once created, these profiles appear in the Properties/PublishProfiles folder within the project. If you have multiple projects, you may need to run separate MSBuild commands for each, or use a loop in your pipeline to iterate through the projects. For example, if you have WebApp.csproj and WorkerService.csproj, you might need distinct steps or complex arguments that specify the exact project file path along with the deploy flags.

Using the Dotnet Command Alternative

For modern .NET Core and .NET 5+ solutions, using the dotnet CLI often provides clearer control than the legacy MSBuild task. The dotnet publish command allows you to target specific projects explicitly. In your pipeline, replace the generic Build task with a Dotnet task set to the "publish" command.
dotnet publish src/WebApp/WebApp.csproj -c Release --output $(build.artifactStagingDirectory)/WebApp
dotnet publish src/Worker/Worker.csproj -c Release --output $(build.artifactStagingDirectory)/Worker
This approach ensures that both projects are published independently into their respective folders. It avoids the ambiguity of MSBuild trying to guess which project to publish. This method is particularly effective when dealing with mixed project types, such as a web front-end and a background service, as it gives you precise control over the output paths and configurations for each component.

Verifying Publish Profiles and Dependencies

Even with correct arguments, publication can fail if the publish profiles are misconfigured or missing dependencies. Ensure that each project intended for publication has a valid .pubxml file in its properties folder. These files define how the project is packaged, including whether it includes dependent assemblies. If a library project relies on other internal projects, those references must be correctly resolved during the publish phase. Check the "Copy Local" property of project references. If set to false, the DLLs might not be copied to the output directory during publish, leading to runtime errors even if the build succeeds. For internal dependencies, ensure they are either published alongside the main project or available in the global assembly cache. Additionally, verify that the pipeline agent has access to any required SDKs or tools needed to restore packages and publish successfully. It is also worth noting that some older frameworks or custom build targets might override default behaviors. If you are using legacy .NET Framework projects, the behavior differs slightly from .NET Core. In those cases, relying on the MSBuild task with explicit _PublishedWebsites targets might be necessary. Always test your pipeline changes in a feature branch before merging to production to avoid deployment failures.

Troubleshooting Common Pitfalls

If your pipeline still publishes only one project after applying these fixes, check the build logs for warnings related to missing profiles or failed targets. Look for messages indicating that MSBuild could not find the specified PublishProfile. Another common issue is caching. Sometimes, old artifacts or cached NuGet packages interfere with the build process. Clearing the cache by adding a clean step before the build can resolve strange inconsistencies. Furthermore, ensure that your solution file itself is not corrupted or pointing to incorrect project paths. Running devenv /clean locally can help verify that the solution builds cleanly outside of the pipeline environment. If you continue to face issues, consider breaking down your monolithic solution into smaller, independent pipelines that handle each project separately. This modular approach reduces complexity and makes troubleshooting significantly easier. For teams managing complex microservices architectures, integrating with container registries via Docker tasks might be a better alternative than traditional file-based publishing. This shifts the focus from individual project outputs to container images, which encapsulate all dependencies. You can explore related techniques for optimizing code analysis or removing unnecessary CI/CD triggers to streamline your workflow further.

Frequently Asked Questions

Why does my build succeed but no files appear in the artifact?

A successful build only produces compiled DLLs in the bin folder; it does not automatically create deployment-ready packages. You must explicitly invoke the publish step or use MSBuild arguments like DeployOnBuild=true to generate the final output files that get uploaded as artifacts.

Can I publish all projects with a single MSBuild command?

Technically yes, but it is unreliable. MSBuild will typically only publish the project with the default profile or the startup project. To guarantee all projects are published, you should either specify each project's profile individually or use separate pipeline steps for each project.

What is the difference between Build and Publish in Azure DevOps?

Build compiles source code into binaries and runs tests, while Publish transforms those binaries into a format suitable for deployment, such as a zip file or a folder structure. Publish also handles dependency resolution and configuration transformations that Build does not perform.

How do I fix missing DLLs in the published output?

Ensure that your project references have "Copy Local" set to true so that dependent assemblies are included in the output. Additionally, verify that your publish profile is configured to include all necessary content files and that no exclusion rules are accidentally filtering them out.

Is Dotnet CLI better than MSBuild for multi-project solutions?

Dotnet CLI offers more predictable behavior for .NET Core and newer versions, allowing explicit targeting of each project. MSBuild can be ambiguous in large solutions with mixed project types, making Dotnet CLI a preferred choice for clarity and control in modern pipelines.

Latest News

How to Display Output of xterm Command in Terminal Screen using Cron

Resolve the inability to display xterm output in a terminal screen from cron by redirecting logs or using wall instead of insecure X11 workarounds.

Read More
Expose Local Server on VPS Preserving Real Client IPs (OS Level)

Resolve VPS logging showing only gateway IPs by configuring reverse proxies to forward real client addresses via X-Forwarded-For headers.

Read More
How to Clear Recent Files History in Linux without Deleting Actual Files?

Clear recent files history in Linux by deleting ~/.local/share/recently-used.xbel without removing the actual files.

Read More
Best HDD Copy Strategy: Manually Syncing and Rewriting Scratch

Resolve data drift between two 4TB hard drives by using rsync with the --delete flag to manually sync and rewrite scratch data for an exact mirror.

Read More
Understanding Bash Prompt Abbreviations: An Overview

Resolve repetitive typing errors by creating and persisting Bash aliases in the .bashrc file for improved command-line efficiency.

Read More
Free Tools and Methods to Log Real-Time Performance Details in Task Manager

Log real-time CPU and memory metrics to CSV files using Windows Performance Monitor Data Collector Sets to troubleshoot system slowness.

Read More
Contact Qatar Airways Customer Service: Phone Number, Help Center, and More

Resolve urgent Qatar Airways reservation issues like flight changes and baggage claims using the US phone number +1801-855-5905 or online self-service tools.

Read More
Windows 11: Alt Codes Displaying Wrong Characters - Solutions

Resolve Windows 11 Alt codes showing wrong characters by verifying the US keyboard layout and enabling Num Lock.

Read More
Run Programs with Elevated Privileges: A Comprehensive Guide

Eliminates the need to type sudo for frequent administrative tasks by configuring .bashrc aliases or functions.

Read More
Dynamically Changing Dates in Excel Formulas Using Cells

Eliminate manual date updates in Excel by using cell references to create dynamic formulas that automatically adjust calculations when input dates change.

Read More
Granting Edit Access to a Specific Excel Sheet in an Office 365 User Email ID-Based Login

Excel Online lacks native sheet-level permissions, so users must split workbooks or use worksheet protection to isolate edit access for specific tabs.

Read More
Creating Network Load on Local Wi-Fi from One PC

Generate sustained Wi-Fi bandwidth load from a single PC using a VM SFTP server to test router stability and throughput.

Read More
Changing the Default Editor for Batch Files in Windows 11's File Explorer

Resolve the issue of batch files opening in Notepad by changing the default editor to a preferred application like VS Code.

Read More
Gain WiFi Connection Minutes Before Losing it by Changing MAC Address

Bypass MAC address filtering to restore WiFi connectivity temporarily when a device is blocked by network administrators.

Read More
Photos Folders Turned Black: Troubleshooting Picture Applications on Windows

Resolve black screens in Windows Photos by resetting the app, updating graphics drivers, and repairing system files.

Read More
Troubleshooting High CPU Temperature Values: A Step-by-Step Guide

Resolve high CPU temperatures and thermal throttling by monitoring with Speedfan, cleaning dust from cooling components, and replacing degraded thermal paste.

Read More
Make cURL establish TLS connection with CA unknown

Resolve cURL TLS connection failures with unknown or self-signed certificates by using the --insecure flag to bypass CA validation.

Read More
Troubleshooting Incorrect Network Metrics Values in Grafana, Prometheus, InfluxDB, and Telegraf

Fix incorrect network metrics in Grafana, Prometheus, InfluxDB, and Telegraf by verifying interface selection, resolving unit mismatches, and handling counter resets.

Read More
Start Another Terminal Window (cmd.exe) Windows Repair/Troubleshoot

Provides step-by-step instructions to access the Windows Command Prompt via bootable media for advanced system repair and troubleshooting.

Read More
Thinkpad P1 Gen 6: Sudden Thunderbolt 3 Dock USB-C Charging Stopped Working

Resolve sudden Thunderbolt 3 dock USB-C charging and internet failure on ThinkPad P1 Gen 6 by updating firmware, resetting the dock, and adjusting power settings.

Read More
ASUS Windows 11 Laptop: Internet Connection Issue with Hotspot

Resolve ASUS Windows 11 laptop spinning wheel issue when connecting to mobile hotspot by resetting network stack, disabling IPv6, and adjusting power settings.

Read More
Developing iOS Project with Firebase: Logging in and Sending Push Notifications

Integrates Firebase to enable secure user authentication and push notifications in iOS applications.

Read More
Troubleshooting Bash Script with Suspected Issues of Spaces, Dashes, Filenames and Quoting

Resolve Bash script failures caused by word splitting, globbing, and special characters in filenames by applying proper quoting techniques.

Read More
Populating OneDrive Folder for Local Backup without Affecting Remote Files

Prevent OneDrive from deleting remote files during Windows reinstallation by unlinking the account or using symbolic links to isolate local data.

Read More
Force First Frame as Keyframe Without Re-encoding: A Quick Solution

Resolve inaccurate seeking and playback glitches by re-encoding video to ensure the first frame is a valid keyframe.

Read More
Find Information in Database Using WSL (Ubuntu) on Windows-10

Resolve database connection issues from WSL Ubuntu on Windows 10 by configuring client tools and network access to query remote or local servers.

Read More
Configuring a New Router with Different Networks: One Family, One Guest

Resolve IP conflicts and isolate guest traffic by configuring a second router with a distinct subnet via its WAN port.

Read More
Quickly Open Multiple Stock Websites with a Single Command

Solve the problem of manually opening multiple stock research websites by creating a single command to launch them simultaneously on Windows, macOS, or Linux.

Read More
Improved Adobe Acrobat Search Experience: Access Advanced Search with Ease

Access advanced search filters like case sensitivity and regex in Adobe Acrobat by clicking More Options in the Find bar.

Read More
Port Forwarding VM via OpenVPN: A Comprehensive Guide

Configure OpenVPN server and iptables to forward specific ports from VPN clients to a virtual machine's internal IP address.

Read More
Understanding Partitions in the 1980s: A Look Back at MS-DOS and Master Boot Record

Explains how the Master Boot Record and partition table enabled MS-DOS to manage multiple disk volumes on a single physical drive.

Read More
Windows 10 Enterprise: Keyboard Not Detected in Managed Organization with Admin Privileges

Resolve Windows 10 Enterprise keyboard detection failures caused by Group Policy restrictions, driver corruption, or USB enumeration errors.

Read More
Can't Find x86_64 Versions of Applications on MacOS arm64 (M1)

Resolve missing x86_64 app issues on M1 Macs by installing Rosetta 2 and reinstalling apps as universal binaries.

Read More
How to Hide Installation Source for an Android App

Manage Android app installation source visibility by using USB transfers or file managers to reduce browser traces and isolate data via work profiles.

Read More
Connecting Momentus 4200.2 ST9808210A Hard Drive via USB Cable

Resolve inability to access Seagate Momentus 4200.2 ST9808210A hard drive by connecting it via USB using a compatible SATA-to-USB adapter and configuring the disk in Windows.

Read More