Skip to content

MSBuildWorkspace should open old-style .NET Framework projects when the NetFramework build host selects VS2026 MSBuild #82931

@rexsacrorum

Description

@rexsacrorum

Title

MSBuildWorkspace should open old-style .NET Framework projects when the NetFramework build host selects VS2026 MSBuild

Body

Version Used:

  • Microsoft.CodeAnalysis.Workspaces.MSBuild 5.3.0
  • Microsoft.CodeAnalysis.CSharp.Workspaces 5.3.0
  • Visual Studio 2026 Community 18.4.2
  • OS: Windows 11 Insider 10.0.26200
  • .NET SDK: 10.0.201
  • .NET runtime: 10.0.5

Steps to Reproduce:

A single public repro repo is enough for this issue: https://github.com/glidermcp/roslyn-VS2026-issue

That repo contains three relevant pieces:

  • Failing sample project: https://github.com/glidermcp/roslyn-VS2026-issue/blob/main/repros/xmakeelements-public-sample/Public.Legacy.Eval.csproj
  • This is the minimal old-style MSBuild project targeting .NET Framework v4.8, importing Microsoft.Common.props and Microsoft.CSharp.targets, with a single Class1.cs file.
  • Roslyn repro runner: https://github.com/glidermcp/roslyn-VS2026-issue/blob/main/repros/roslyn-msbuildworkspace-repro/roslyn-msbuildworkspace-repro.csproj
  • Runner source: https://github.com/glidermcp/roslyn-VS2026-issue/blob/main/repros/roslyn-msbuildworkspace-repro/Program.cs
  • This is the actual failing repro. It is a small standalone Roslyn MSBuildWorkspace program and does not use any production-specific code or Microsoft.Build.Locator.
  • Optional control runner: https://github.com/glidermcp/roslyn-VS2026-issue/tree/main/repros/msbuild-locator-net472
  • This is not required to reproduce the Roslyn failure. It is included only as a control to show that the same VS2026 MSBuild bits succeed in a standalone net472 host outside Roslyn.

The Roslyn repro runner directly:

  1. prints the preferred Roslyn build host kind via reflection
  2. calls MSBuildWorkspace.OpenProjectAsync(...)
  3. prints the exception chain and workspace failures

Run:

git clone https://github.com/glidermcp/roslyn-VS2026-issue.git
Set-Location .\roslyn-VS2026-issue\repros\roslyn-msbuildworkspace-repro
dotnet run -- ..\xmakeelements-public-sample\Public.Legacy.Eval.csproj

Relevant output:

Preferred host for original project: NetFramework
RESULT: failure
[0] Microsoft.CodeAnalysis.MSBuild.RemoteInvocationException: An exception of type System.TypeInitializationException was thrown: The type initializer for 'Microsoft.Build.Shared.XMakeElements' threw an exception.

Roslyn also reports workspace failures during build-host shutdown, including that the BuildHost process is not responding.

Expected Behavior:

MSBuildWorkspace.OpenProjectAsync(...) should succeed for the attached sample. If the project is invalid, the build host should surface the underlying cause clearly.

Actual Behavior:

When Roslyn selects the NetFramework build host for this old-style .NET Framework project, MSBuildWorkspace.OpenProjectAsync(...) fails with a remote exception wrapping:

System.TypeInitializationException: The type initializer for 'Microsoft.Build.Shared.XMakeElements' threw an exception.

The same project shape succeeds outside Roslyn's NetFramework build host.

Additional Context:

These all succeed on the same machine with the same VS2026 MSBuild installation:

Set-Location .\roslyn-VS2026-issue

dotnet msbuild .\repros\xmakeelements-public-sample\Public.Legacy.Eval.csproj /nologo /t:Restore

"C:\Program Files\Microsoft Visual Studio\18\Community\MSBuild\Current\Bin\MSBuild.exe" `
  .\repros\xmakeelements-public-sample\Public.Legacy.Eval.csproj /nologo /t:Restore

dotnet run --project .\repros\msbuild-locator-net472\msbuild-locator-net472.csproj -- `
  "C:\Program Files\Microsoft Visual Studio\18\Community\MSBuild\Current\Bin" `
  ".\repros\xmakeelements-public-sample\Public.Legacy.Eval.csproj"

Standalone locator repro success output includes:

MSBuildLocator registration: success
XMakeElements initialization: success
Project evaluation returned instance type: Microsoft.Build.Evaluation.Project
Roslyn-style project evaluation returned instance type: Microsoft.Build.Evaluation.Project
RESULT: success

Additional observations:

  • The failure reproduces on a stripped public sample with no customer code.
  • The failure signature is stable after removing unrelated project content.
  • The failure also reproduces after removing Microsoft.Build.Locator entirely from the failing Roslyn repro project, which suggests locator is not required to trigger the failure.
  • The failing behavior appears specific to Roslyn's NetFramework build-host path on this machine.
  • The NetCore build host remains healthy on the same machine.

Why this looks Roslyn-specific:

The same MSBuild bits work when invoked directly and when hosted by a standalone net472 control program. The failure appears only when those bits are loaded inside Roslyn's net472 build-host executable path.

That suggests the likely fix area is one of:

  • build-host assembly binding or probing context
  • build-host process startup or registration environment
  • Roslyn net472 host packaging assumptions against VS2026 MSBuild layout
  • an interaction between Roslyn's build-host loading path and MSBuild static initialization that is not present in direct-host scenarios

Metadata

Metadata

Labels

Type

No type
No fields configured for issues without a type.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions