Skip to content

Fix dotnet host detection using GetFileNameWithoutExtension#53157

Merged
MichaelSimons merged 3 commits intodotnet:mainfrom
MichaelSimons:fix/getfilenamewithoutextension-dotnet-detection
Feb 26, 2026
Merged

Fix dotnet host detection using GetFileNameWithoutExtension#53157
MichaelSimons merged 3 commits intodotnet:mainfrom
MichaelSimons:fix/getfilenamewithoutextension-dotnet-detection

Conversation

@MichaelSimons
Copy link
Member

Summary

Multiple locations in the codebase use Path.GetFileNameWithoutExtension to check whether the current process is the dotnet host. This is incorrect because GetFileNameWithoutExtension treats any dot-separated suffix as a file extension — for example, GetFileNameWithoutExtension("dotnet.Tests") returns "dotnet", which is a false positive match.

This was discovered during the xUnit v3 migration (#52930), where tests run as standalone executables named dotnet.Tests. The test GivenAProjectToolsCommandResolver.ItWritesADepsJsonFileNextToTheLockfile was failing because Muxer incorrectly treated the dotnet.Tests process as the dotnet host, causing ProjectToolsCommandResolver.GenerateDepsJsonFile to invoke dotnet.Tests exec MSBuild.dll ... instead of the real dotnet host, resulting in:

GracefulException: Unable to generate deps.json, it may have been already generated.

Fix

All affected locations now use Path.GetFileName and compare against the full executable name (dotnet on Linux, dotnet.exe on Windows), matching the pattern already established in EnvironmentProvider.GetDotnetExeDirectory. Duplicate inline computations of the dotnet filename were unified into shared fields (Constants.DotNetFileName, Muxer.muxerFileName).

Testing

Added ItDoesNotMistakeDotnetPrefixedProcessForDotnetHost test that verifies GetDotnetExeDirectory falls through to PATH-based lookup when the process path is a dotnet-prefixed name like dotnet.Tests.

Path.GetFileNameWithoutExtension treats dot-separated suffixes as file
extensions, so 'dotnet.Tests' is incorrectly identified as 'dotnet'.
This causes failures when the process is a dotnet-prefixed executable
rather than the actual dotnet host.

Replace GetFileNameWithoutExtension with GetFileName and compare against
the full executable name (e.g. 'dotnet' on Linux, 'dotnet.exe' on
Windows) in all affected locations:

- Muxer.cs: unify muxer filename into a single local variable
- EnvironmentProvider.cs: use Constants.DotNetFileName
- EnvironmentOptions.cs (dotnet-watch): fix Debug.Assert
- ServerConnection.cs (Razor): fix FindDotNetExecutable
- MSBuildSdkResolver.cs: unify with Constants.DotNetFileName
- Constants.cs: add DotNetFileName, remove DotNetExe

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR fixes incorrect “dotnet host” detection caused by using Path.GetFileNameWithoutExtension (which can treat dot-separated suffixes like dotnet.Tests as an extension), and updates call sites to compare against the full executable filename instead.

Changes:

  • Replace GetFileNameWithoutExtension-based dotnet-host checks with Path.GetFileName comparisons against the platform-specific dotnet executable name.
  • Introduce and use a shared Constants.DotNetFileName to centralize dotnet vs dotnet.exe selection.
  • Add a regression test ensuring dotnet-prefixed process names (e.g., dotnet.Tests) don’t get mistaken for the dotnet host.

Reviewed changes

Copilot reviewed 7 out of 7 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
test/Microsoft.DotNet.MSBuildSdkResolver.Tests/GivenAnEnvironmentForResolution.cs Adds a regression test for dotnet-prefixed process-name host detection; updates test class to SdkTest.
src/Resolvers/Microsoft.DotNet.NativeWrapper/EnvironmentProvider.cs Updates host detection to use Path.GetFileName and Constants.DotNetFileName.
src/Resolvers/Microsoft.DotNet.NativeWrapper/Constants.cs Introduces DotNetFileName (platform-specific dotnet executable filename).
src/Resolvers/Microsoft.DotNet.MSBuildSdkResolver/MSBuildSdkResolver.cs Uses Constants.DotNetFileName when constructing muxer/dotnet paths.
src/RazorSdk/Tool/ServerProtocol/ServerConnection.cs Fixes dotnet detection to use full filename rather than filename-without-extension.
src/Cli/Microsoft.DotNet.Cli.Utils/Muxer.cs Fixes muxer detection to use full filename; centralizes computed muxer filename within ctor.
src/BuiltInTools/Watch/Context/EnvironmentOptions.cs Updates debug assertion to validate full muxer filename instead of filename-without-extension.

Copy link
Member

@baronfel baronfel left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

😬

Good find - I suspect this is one of those things that would also become more clear if/when we had the unified 'path resolver' infrastructure.

MichaelSimons and others added 2 commits February 25, 2026 12:03
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
@MichaelSimons
Copy link
Member Author

/ba-g Known Linux failure.

@MichaelSimons MichaelSimons enabled auto-merge (squash) February 26, 2026 14:56
@MichaelSimons MichaelSimons merged commit db01067 into dotnet:main Feb 26, 2026
24 of 26 checks passed
@MichaelSimons MichaelSimons deleted the fix/getfilenamewithoutextension-dotnet-detection branch February 26, 2026 15:07
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.

4 participants