Repository navigation
[Breaking change]: Environment.GetCommandLineArgs()[0] preserves the executable invocation name #56357
Description
Description
Starting in .NET 11, Environment.GetCommandLineArgs()[0] preserves the name or path used to invoke an application when it is launched through its apphost executable.
Previously, the first element of the array contained the managed assembly path or, for single-file applications, the resolved executable path. As a result, it did not necessarily reflect how the application was invoked, particularly when the executable was launched through a symbolic link.
With the new behavior, Environment.GetCommandLineArgs()[0] reflects the original invocation name, including relative paths and symbolic link names, rather than a resolved path.
Applications launched using dotnet <application.dll> retain their existing behavior.
Version
.NET 11 Preview 7
Previous behavior
When an application was launched through its apphost executable, Environment.GetCommandLineArgs()[0] returned the managed assembly path or, for single-file applications, the resolved executable path.
For example, consider an application named foo and a symbolic link named special_myapp pointing to its executable:
ln -s foo special_myapp
./special_myapp 1 2 3
Previously, Environment.GetCommandLineArgs()[0] did not preserve ./special_myapp. Instead, it returned the fully resolved managed assembly path (myapp.dll) or the resolved executable path (myapp), depending on the deployment model.
New behavior
When an application is launched through its apphost executable, Environment.GetCommandLineArgs()[0] preserves the original executable invocation name.
For example, ./special_myapp 1 2 3 from the example above now returns ./special_myapp.
Type of breaking change
- Binary incompatible: Existing binaries might encounter a breaking change in behavior, such as failure to load or execute, and if so, require recompilation.
- Source incompatible: When recompiled using the new SDK or component or to target the new runtime, existing source code might require source changes to compile successfully.
- Behavioral change: Existing binaries might behave differently at run time.
Reason for change
Previously, Environment.GetCommandLineArgs()[0] did not consistently reflect how an application was invoked. In particular, applications launched through symbolic links could not use this API to determine the invocation name.
The new behavior aligns more closely with the native process argument convention, where argv[0] represents the invocation name supplied to the process.
This change enables applications to distinguish between different invocation names, including symbolic links.
Recommended action
If your application relies on Environment.GetCommandLineArgs()[0] to retrieve the managed assembly path or resolved executable path, review the code to determine whether the new behavior affects it.
Depending on your requirements:
Use Environment.ProcessPath to retrieve the path to the executable associated with the current process.
Use Assembly.GetEntryAssembly()?.Location when you need the managed entry assembly location. Note that this property returns an empty string for bundled assemblies in single-file applications.
Continue using Environment.GetCommandLineArgs()[0] when you need the original executable invocation name.
Feature area
Core .NET libraries
Affected APIs
System.Environment.GetCommandLineArgs()
Metadata
Metadata
Assignees
Labels
Type
Projects
- StatusShow more project fields✅ Done
Activity