Skip to content

Add App Host Support for MSBuild#13175

Merged
YuliiaKovalova merged 60 commits intomainfrom
dev/ykovalova/app_host_support
Mar 3, 2026
Merged

Add App Host Support for MSBuild#13175
YuliiaKovalova merged 60 commits intomainfrom
dev/ykovalova/app_host_support

Conversation

@YuliiaKovalova
Copy link
Member

@YuliiaKovalova YuliiaKovalova commented Feb 2, 2026

Part 1 of: #12995

Context

This PR implements App Host support for MSBuild, enabling MSBuild to run as a native executable (MSBuild.exe or MSBuild on Unix) instead of dotnet + MSBuild.dll

Changes Made

Added DotnetHostEnvironmentHelper class to manage DOTNET_ROOT environment variables

When MSBuild runs as an app host, child processes (worker nodes and task hosts) need DOTNET_ROOT set to locate the .NET runtime
These variables are cleared after startup so they don't leak to tools executed by child processes
Only clears DOTNET_ROOT variants if they weren't present in the original build process environment

Node Launcher Updates

Updated NodeLauncher to pass environment overrides when launching worker nodes
NodeLaunchData record struct with EnvironmentOverrides support
Implemented BuildEnvironmentBlock for Windows process creation with custom environment
NodeProviderOutOfProc and NodeProviderOutOfProcTaskHost now provide DOTNET_ROOT overrides

Notes

Backward compatible: Falls back to dotnet MSBuild.dll if app host doesn't exist (older SDKs)
Uses ProcessStartInfo.Environment for thread-safe, scoped environment overrides
The SDK can continue using dotnet MSBuild.dll or opt to use the new app host—this is not a forced change

@YuliiaKovalova YuliiaKovalova self-assigned this Feb 2, 2026
@YuliiaKovalova
Copy link
Member Author

@copilot could you please move all $(LatestDotNetCoreForMSBuild) related changes to a separate PR?

Copy link
Contributor

Copilot AI commented Feb 3, 2026

@YuliiaKovalova I've opened a new pull request, #13189, to work on those changes. Once the pull request is ready, I'll request review from you.

@YuliiaKovalova YuliiaKovalova force-pushed the dev/ykovalova/app_host_support branch from 90e06c7 to 95f4da2 Compare February 3, 2026 16:46
DustinCampbell added a commit to DustinCampbell/msbuild that referenced this pull request Feb 27, 2026
I had introduced TaskHostLaunchArgs to consolidate some of the logic used to gather the arguments need to launch nodes. However, this will conflict with another change that is currently out for review: dotnet#13175. This change replaces TaskHostLaunchArgs with a NodeLaunchData type that looks more like the one in dotnet#13175. It is not identical, but it should make it a bit easier to merge the two changes.
…ost_support

Conflicts:
	src/Build/BackEnd/Components/Communications/INodeLauncher.cs
	src/Build/BackEnd/Components/Communications/NodeProviderOutOfProcTaskHost.cs
	src/MSBuildTaskHost/MSBuildTaskHost.csproj
@rainersigwald
Copy link
Member

I tried to merge with #13232 but I don't feel great about what I did -- fyi @YuliiaKovalova.

@rainersigwald
Copy link
Member

macOS tests failed flakily -- put up #13316 and rerunning.

@YuliiaKovalova YuliiaKovalova merged commit c8011cb into main Mar 3, 2026
10 checks passed
@YuliiaKovalova YuliiaKovalova deleted the dev/ykovalova/app_host_support branch March 3, 2026 10:31
JanProvaznik added a commit that referenced this pull request Mar 3, 2026
PR #13175 accidentally replaced the ItemsToSign Include for the XSD
update script with a conditional Remove, meaning the file was never
added to signing. CodeSignValidation then flagged it as unsigned.

Restore the original unconditional Include. The file is produced by the
CopyXsds target in MSBuild.csproj and is consumed by VS insertion
(CustomScriptExecutionCommand in vs-insertion.yml). It must be signed
in the MSBuild official build.

In source-build (dotnet/dotnet on Linux), signing is test/disabled so
the Include is harmless. The dotnet official build does not run
CodeSignValidation on component-level artifacts.

Fixes AB#2787495

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
JanProvaznik added a commit that referenced this pull request Mar 3, 2026
PR #13175 accidentally replaced the ItemsToSign Include for
Update-MSBuildXsds.ps1 with a Remove (which was a no-op since
the file was never included by default). This caused
CodeSignValidation to flag the file as unsigned.

Restore the Include with an Exists() guard so that signing works
in the MSBuild official build (where CopyXsds produces the file)
and doesn't break in contexts where the file may not exist.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
rainersigwald pushed a commit that referenced this pull request Mar 3, 2026
PR #13175 accidentally replaced the `ItemsToSign Include` for
`Update-MSBuildXsds.ps1` with a conditional `Remove`, meaning the file
was never added to signing. CodeSignValidation then flagged it as
unsigned (`CodeSign.MissingSigningCert`).

## Change

Restore the original unconditional `Include` in `eng/Signing.props`. The
broken `Remove` (which was removing an item that was never added) is
deleted.

Fixes AB#2787495

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
YuliiaKovalova added a commit that referenced this pull request Mar 4, 2026
Three bugs introduced by c8011cb (Add App Host Support for MSBuild):

1. CLR2 task host (MSBuildTaskHost.exe) broken on .NET Core MSBuild:
   ResolveExecutableName only recognized MSBuild.exe as a native executable.
   Any other .exe (like MSBuildTaskHost.exe) was incorrectly routed through
   dotnet.exe, which cannot host .NET Framework 3.5 executables.
   Fix: detect native executables by checking for .dll extension instead of
   matching a specific filename. Only .dll files need dotnet.exe as host.

2. .NET task host fallback broken when DotnetHostPath is null:
   ResolveAppHostOrFallback created NodeLaunchData with null MSBuildLocation
   when apphost was missing and TaskHostParameters.DotnetHostPath was not set.
   Fix: auto-discover dotnet host via CurrentHost.GetCurrentHost() when the
   parameter is null.

3. MSB4216 error shows wrong executable path for .NET task hosts:
   LogErrorUnableToCreateTaskHost had a #if NETFRAMEWORK guard that prevented
   it from using the correct .NET path when running on .NET Core. It always
   showed the non-.NET path (MSBuild.exe) regardless of task host type.
   Fix: check HandshakeOptions.NET on all runtimes, not just .NET Framework.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
YuliiaKovalova added a commit that referenced this pull request Mar 4, 2026
## Summary

Fixes three regressions introduced by #13175 (Add App Host Support for
MSBuild, commit c8011cb).

## Bug 1: CLR2 task host (MSBuildTaskHost.exe) broken - VS build
failures

**Root cause**: `NodeLauncher.ResolveExecutableName` only recognized
`MSBuild.exe` (`Constants.MSBuildExecutableName`) as a native
executable. Any other `.exe` - including `MSBuildTaskHost.exe` - was
treated as a managed assembly and routed through `dotnet.exe`. Since
`MSBuildTaskHost.exe` is a standalone .NET Framework 3.5 executable,
`dotnet.exe` cannot host it.

## Bug 2: .NET task host fallback broken when `DotnetHostPath` is null

**Symptom**: `MSB4216: ... the required executable
"...\sdk\11.0.100-ci\MSBuild.exe" exists and can be run` - in CI where
the apphost hasn't been created yet.

**Root cause**: `ResolveAppHostOrFallback` correctly detects the missing
apphost and tries to fall back to `dotnet MSBuild.dll`, but
`TaskHostParameters.DotnetHostPath` is null (not populated by
`AssemblyTaskFactory`). This produces `NodeLaunchData(null, ...)` which
silently fails in `CreateNode`.

## Bug 3: MSB4216 error shows wrong executable path for .NET task hosts

**Root cause**: `LogErrorUnableToCreateTaskHost` in `TaskHostTask.cs`
has a `#if NETFRAMEWORK` guard around the .NET task host path
resolution. On .NET Core (the common case), it always falls through to
`GetMSBuildExecutablePathForNonNETRuntimes` which returns the non-.NET
path (`MSBuild.exe`), even for `.NET` task host failures.

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Rainer Sigwald <raines@microsoft.com>
YuliiaKovalova added a commit that referenced this pull request Mar 9, 2026
…mple (#13324)

Update `remote-host-object.md` with documentation for the MSBuild
apphost changes.

### What's added

1. **Shipping `Microsoft.Build.Framework.tlb` with the .NET SDK** -
documents that the `.tlb` ships starting from 10.0.3xx, explains why
it's needed (COM marshaling for `ITaskHost` across process boundaries),
what capabilities it enables (ROT host objects, registration-free COM,
parity with VS), and shows the SDK layout.

2. **Practical `IDispatch` example** - end-to-end example showing how a
VS host object (WebTools) serializes task items to JSON via
`QueryAllTaskItems`, and how the SDK Container task
([dotnet/sdk#52856](dotnet/sdk#52856)) calls it
via `IDispatch` (reflection `InvokeMember`) with a fallback to the
legacy in-proc path.

Related PRs:
- #13175 (Add App Host Support for MSBuild)
- dotnet/sdk#52856 (Refactor VSHostObject for COM compatibility)
- [WebTools PR
701336](https://dev.azure.com/devdiv/DevDiv/_git/WebTools/pullrequest/701336)

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Rainer Sigwald <raines@microsoft.com>
rainersigwald added a commit to rainersigwald/msbuild that referenced this pull request Mar 11, 2026
There was a collision between dotnet#13220 (at end of build, look for other
running MSBuild processes and decide whether node reuse is likely to be
worthwhile) and dotnet#13175 (use an apphost on core). This broke the
overprovisioning detection, which was looking for `dotnet[.exe]` instead
of the new `MSBuild[.exe]`.

Always search for `MSBuild[.exe]` instead, and remove the now-unnecesary
"try to filter `dotnet.exe` processes to those running `MSBuild.dll`
code too.
rainersigwald added a commit that referenced this pull request Mar 11, 2026
There was a collision between #13220 (at end of build, look for other
running MSBuild processes and decide whether node reuse is likely to be
worthwhile) and #13175 (use an apphost on core). This broke the
overprovisioning detection, which was looking for `dotnet` instead
of the new `MSBuild`.

Always search for `MSBuild` instead, and remove the now-unnecesary
"try to filter `dotnet.exe` processes to those running `MSBuild.dll`
code too.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

7 participants