Hacktoberfest 2026: los issues que los mantenedores marcaron para octubre, abiertos y aptos para principiantes. Explorar issues de Hacktoberfest

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

Cerrado
#2,850 0 comentarios 0 reacciones 0 asignados Ver en GitHub

@adamsitnik ya está trabajando en esto.

Desde el 12/10/2026.

  • #2855 de @adamsitnik — abierto

Evaluación

Dificultad
3/5
Tiempo estimado
1-2 días
Aptitud para principiantes
76/100
Tipo de issue
Error
Claridad
Bien especificado
Estado de actividad
Activo
Stack tecnológico
csharp
Área
cli

Línea de trabajo

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.

Escrito por el modelo de indexación a partir del texto del issue.

Descripción

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

Lenguaje dominante
C#
Estrellas
3.7k
Forks
434
Merge medio
6 h 27 min
PR fusionados (30 d)
2

Preparar el entorno

Primeros pasos

  1. Lee el issue completo y luego la guía de contribución del proyecto.
  2. Comenta en el issue que vas a ocuparte — evita que dos personas hagan lo mismo.
  3. Haz un fork del repositorio y trabaja en una rama.
  4. Abre un pull request que haga referencia al número del issue.

Más de dotnet/command-line-api

Todos los issues de dotnet/command-line-api

Issues similares

Más issues de C#

Recibe los nuevos issues en tu correo

Un resumen breve de issues de GitHub para principiantes.