You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Use C# Dev Kit selected workspace dotnet host for debugger prerequisite checks #9732
When C# Dev Kit owns workspace SDK selection through Workspace Requirements, the C# extension still independently runs dotnet --info against its own configured paths/ambient PATH during debugger activation.
In a Remote SSH Linux workspace with no ambient dotnet on PATH, this produces two competing remediations at once:
C# Dev Kit opens Workspace Requirements with Install .NET 10 SDK.
The C# extension shows The .NET SDK cannot be located with Get the SDK.
The C# notification is especially confusing because its Get the SDK action already delegates to csdevkit.installDotnetSdk when C# Dev Kit is present, while the prerequisite check that raised it did not use C# Dev Kit's selected host or blocked state.
Observed with:
C# Dev Kit 9.9.554-g91f1bb
C# 2.140.9
VS Code Remote SSH to Ubuntu 24.04 x64
no ambient dotnet on the remote PATH
Relevant current code:
src/coreclrDebug/util.ts: checkDotNetCli() runs dotnet --info using C# extension paths.
src/coreclrDebug/activate.ts: showDotnetToolsWarning() routes Get the SDK to csdevkit.installDotnetSdk when Dev Kit is present.
src/utils/getCSharpDevKit.ts and src/csharpDevKitExports.ts: C# already discovers and consumes C# Dev Kit exports, but there is no selected workspace host/readiness contract.
Expected behavior
C# Dev Kit should be the single SDK/host authority when it is active and dotnet.preferCSharpExtension is not selected:
C# obtains the exact workspace dotnet executable and environment selected by C# Dev Kit before debugger prerequisite checks.
If Workspace Requirements is blocked and has opened its remediation UI, C# does not show a second SDK-install notification.
After the user installs or selects the SDK and reloads, both extensions use the same host.
When C# Dev Kit is absent or explicitly bypassed, C# retains its current standalone discovery and notification behavior.
A minimal contract could be an optional C# Dev Kit export returning { status: ready | blocked, dotnetPath?, environment? }. Because workspace host changes are already reload-bound, this does not require live language-server/debugger host switching.
C# adds an optional, feature-detected getWorkspaceDotnetHost() member to its local C# Dev Kit export shape. It reuses the existing asynchronous Dev Kit activation callback rather than synchronously awaiting Dev Kit activation from C# activation.
Only debugger prerequisite completion is deferred. The result is bounded and rejection-safe:
Dev Kit absent or bypassed with dotnet.preferCSharpExtension: existing standalone C# behavior.
Old Dev Kit without the optional method: existing standalone fallback.
Dev Kit activation/export rejection: handled standalone fallback.
New Dev Kit reports blocked: skip ambient probing and suppress the competing C# SDK notification.
New Dev Kit reports ready: use the exact selected executable and environment for dotnet --info, dotnet --list-runtimes, debugger architecture selection, and DOTNET_ROOT.
New Dev Kit reports not-applicable: existing standalone fallback.
C# Dev Kit's additive export projects its existing immutable Workspace Requirements selection as only ready, blocked, or not-applicable. It does not add mutable policy or live host swapping. Managed, external, and explicit user-owned hosts all return their already-selected absolute executable and environment. Reload-required states do not claim a future host is usable by the current process.
Validation completed
C#: TypeScript compile, changed-file ESLint, development package build, 39 unit suites / 410 tests passed (1 skipped), plus 9 focused compatibility tests.
C# Dev Kit: TypeScript compile, changed-file ESLint, webpack build, and 101 focused Workspace Requirements/readiness tests passed.
Combined real VS Code Extension Development Host with both modified extensions and no ambient dotnet on PATH: Workspace Requirements opened in blocked state; the notification center did not contain The .NET SDK cannot be located.
The PR descriptions include full compatibility matrices. Remote SSH old/new/absent-build validation remains called out as release validation rather than being inferred from the local extension-host run.
Activity
JakeRadMSFT commentedon Sep 4, 2026
Implemented the two-phase compatibility design in separate PRs:
Final design
C# adds an optional, feature-detected
getWorkspaceDotnetHost()member to its local C# Dev Kit export shape. It reuses the existing asynchronous Dev Kit activation callback rather than synchronously awaiting Dev Kit activation from C# activation.Only debugger prerequisite completion is deferred. The result is bounded and rejection-safe:
dotnet.preferCSharpExtension: existing standalone C# behavior.blocked: skip ambient probing and suppress the competing C# SDK notification.ready: use the exact selected executable and environment fordotnet --info,dotnet --list-runtimes, debugger architecture selection, andDOTNET_ROOT.not-applicable: existing standalone fallback.C# Dev Kit's additive export projects its existing immutable Workspace Requirements selection as only
ready,blocked, ornot-applicable. It does not add mutable policy or live host swapping. Managed, external, and explicit user-owned hosts all return their already-selected absolute executable and environment. Reload-required states do not claim a future host is usable by the current process.Validation completed
dotnetonPATH: Workspace Requirements opened in blocked state; the notification center did not contain The .NET SDK cannot be located.The PR descriptions include full compatibility matrices. Remote SSH old/new/absent-build validation remains called out as release validation rather than being inferred from the local extension-host run.
JakeRadMSFT commentedon Sep 4, 2026
Dev Kit producer PR link correction: the active PR is https://devdiv.visualstudio.com/DevDiv/_git/vs-green/pullrequest/778204. PR 778197 was superseded without force-pushing so the commit could use the required corporate proof-of-presence identity.