Hacktoberfest 2026:维护者为十月标记出来的 issue,仍然开放、适合新手。 浏览 Hacktoberfest issue

RootCommand.ExecutableName truncates dotted app names on Linux/macOS when targeting .NET 11

未关闭
#2,850 0 条评论 0 个 reaction 已指派 0 人 在 GitHub 查看

还没有人认领这个 Issue。

评估

难度
3/5
预计耗时
1-2 天
新手友好度
76/100
Issue 类型
缺陷
描述清晰度
描述清楚
活跃度
活跃
技术栈
csharp
领域
cli

调研方向

Start in src/command-line-api/src/System.CommandLine/RootCommand.cs, focusing on ExecutableName and ExecutablePath, then reproduce the published Contoso.Tool example on Linux or macOS. Compare net10.0 and net11.0 help output; done means dotted apphost names remain intact in RootCommand.ExecutableName and the Usage line.

由索引模型根据 Issue 内容生成。

描述

Summary

Starting with .NET 11, Environment.GetCommandLineArgs()[0] returns the name the apphost was invoked with instead of the managed .dll path (dotnet/runtime#131671). RootCommand.ExecutableName runs Path.GetFileNameWithoutExtension on that value. On Linux/macOS the apphost has no extension, so any app whose name contains a dot has its last segment treated as an "extension" and dropped. For example, Contoso.Tool becomes Contoso.

This affects the root command's Name, so it changes the Usage: line in help output. It also affects everything else derived from ExecutableName. Apps get this just by retargeting from net10.0 to net11.0, with no code changes.

Background: the .NET 11 runtime change

dotnet/runtime#131671, "Fix Environment.GetCommandLineArgs()[0] to report the host invocation name", merged 2026-08-10 and fixes dotnet/runtime#101837. It adds an ARGV0 host runtime property: hostpolicy captures the apphost's native argv[0], and CoreCLR uses it for element zero of Environment.GetCommandLineArgs(). From that PR:

Command line Environment.GetCommandLineArgs()
dotnet.exe foo.dll 1 2 3 foo.dll, 1, 2, 3 (unchanged)
foo 1 2 3 foo, 1, 2, 3 (previously the managed …/foo.dll path)
../bar/special_foo.exe 1 2 3 (symlink to foo.exe) ../bar/special_foo.exe, 1, 2, 3

Before this change, args[0] for an apphost launch always ended in .dll, so GetFileNameWithoutExtension happened to strip a real extension on every OS. Now it's the apphost name:

  • Windows: the apphost name ends in .exe, so stripping the extension is still correct.
  • Linux/macOS: the apphost has no extension, so a dotted name loses its last segment.

The System.CommandLine code involved

2.0.x servicing, e.g. 2.0.12 (dotnet/dotnet release/10.0.1xx, RootCommand.cs#L48-L54):

public static string ExecutableName
    => _executableName ??= Path.GetFileNameWithoutExtension(ExecutablePath).Replace(" ", "");

public static string ExecutablePath => _executablePath ??= Environment.GetCommandLineArgs()[0];

main (RootCommand.cs#L104-L137) has the same core logic: Path.GetFileNameWithoutExtension(path).Replace(" ", "") on L128, where path is Environment.GetCommandLineArgs()[0].

Repro

Contoso.Tool.csproj:

<Project Sdk="Microsoft.NET.Sdk">
  <PropertyGroup>
    <OutputType>Exe</OutputType>
    <TargetFrameworks>net10.0;net11.0</TargetFrameworks>
    <ImplicitUsings>enable</ImplicitUsings>
  </PropertyGroup>
  <ItemGroup>
    <PackageReference Include="System.CommandLine" Version="2.0.12" />
  </ItemGroup>
</Project>

Program.cs:

using System.CommandLine;

Console.WriteLine($"GetCommandLineArgs()[0] = {Environment.GetCommandLineArgs()[0]}");
Console.WriteLine($"RootCommand.ExecutableName = {RootCommand.ExecutableName}");
return new RootCommand("Sample tool").Parse(args).Invoke();

Publish for linux-x64 (I used SDK 11.0.100-rc.1.26425.128), then run ./Contoso.Tool --help on Linux.

net10.0

GetCommandLineArgs()[0] = /…/pub/net10.0/Contoso.Tool.dll
RootCommand.ExecutableName = Contoso.Tool
Description:
  Sample tool

Usage:
  Contoso.Tool [options]

net11.0

GetCommandLineArgs()[0] = ./Contoso.Tool
RootCommand.ExecutableName = Contoso
Description:
  Sample tool

Usage:
  Contoso [options]

On Windows the same net11.0 app still reports Contoso.Tool, because args[0] is Contoso.Tool.exe. The result is the same app showing different names per OS.

Who is affected

Any System.CommandLine app that:

  • targets .NET 11 and is launched through its apphost rather than dotnet app.dll, and
  • runs on Linux or macOS, and
  • has a dot in its executable name. That's common, because the default AssemblyName is the project name, e.g. Contoso.Tool, MyCompany.Cli, or test projects like Foo.Tests.

Impacts:

  • Help output: Usage: shows the wrong command name.
  • Other ExecutableName users: code that uses RootCommand.ExecutableName directly, and features that depend on it, such as completion/dotnet-suggest registration, get the truncated name. A similar issue was fixed earlier for RegisterWithDotnetSuggest in #2316.
  • Tests: help-output snapshot tests become OS-dependent. We hit this in Aspire when retargeting our CLI tests to net11.0: help snapshots started failing only on Linux/macOS, where Aspire.Cli.Tests was rendered as Aspire.Cli (microsoft/aspire#20436). Our shipped aspire binary isn't affected only because its name has no dot.

cc dotnet/runtime#131671, where I also asked whether the runtime change should be tagged as a breaking change: https://github.com/dotnet/runtime/pull/131671#issuecomment-5822378513

主要语言
C#
星标
3.7k
派生
434
PR 合并指标
30 天内没有已合并 PR

环境准备

  • 没有 Dockerfile 或 Docker Compose 文件
  • 没有 Pull Request 模板
  • 阅读贡献指南

从这里开始

  1. 先读完整个 Issue,再读项目的贡献指南。
  2. 在 Issue 下留言说明你要接手 —— 这能避免两个人做同样的事。
  3. Fork 仓库,在一个分支上完成修改。
  4. 提交 Pull Request,并在描述里引用这个 Issue 编号。

dotnet/command-line-api 的其他 Issue

查看 dotnet/command-line-api 的全部 Issue

相似的 Issue

更多 C# Issue

把新 issue 发到你的邮箱

精选适合新手参与的 GitHub issue 摘要。