Skip to content

[API Proposal]: Expose API for escaping command-line arguments #119200

Open

Description

@Youssef1313

Background and motivation

The core logic is in an internal PasteArguments.AppendArgument. But it's not exposed directly for users usage.

While ProcessStartInfo today already supports passing a list of unescaped arguments (ArgumentList property), it cannot be used together with Arguments property.

API Proposal

namespace System.Diagnostics;

public class ProcessStartInfo
{
    public static string EscapeArgument(string argument);
}

API Usage

// Fancy the value
var info = new ProcessStartInfo()
{
    FileName = ...;
}

var builder = new StringBuilder();
builder.Append(myAlreadyEscapedArgumentsComingFromElsewhere);
foreach (var arg in listOfUnescapedArguments)
{
    builder.Append(ProcessStartInfo.EscapeArgument(arg));
}
info.Arguments = builder.ToString(); 

Real-world example is SDK:

https://github.com/dotnet/sdk/blob/15c4fb1e5086e8a61876fd60b612a51cac1774c2/src/Cli/dotnet/Commands/Test/TestApplication.cs#L97

There, Module.RunProperties.Arguments is already a single string which can contain multiple arguments like --report-trx --results-directory "Path Containing Spaces" which is already escaped properly.
Then, there are multiple more arguments that need to be constructed and are not escaped.

NOTE: ArgumentEscaper.EscapeSingleArg implementation seems like it's already diverging from the implementation in dotnet/runtime. And somewhere in dotnet/msbuild there is even another implementation somewhere.

Alternative Designs

Allow both ProcessStartInfo.Arguments and ArgumentList to be used together.

Risks

No response

Activity

  1. added
    api-suggestionEarly API idea and discussion, it is NOT ready for implementation
    on Aug 29, 2025
  2. dotnet-policy-service commented on Aug 29, 2025

    @dotnet-policy-service
    Contributor

    Tagging subscribers to this area: @dotnet/area-system-diagnostics-process
    See info in area-owners.md if you want to be subscribed.

  3. MihuBot commented on Aug 29, 2025

    @MihuBot

    I'm a bot. Here is a possible related and/or duplicate issue (I may be wrong):

  4. adamsitnik commented on Aug 29, 2025

    @adamsitnik
    Member

    ArgumentList predates me as an owner of System.Diagnostics.Process, but my understanding is that it was designed as the new, recommended way of passing arguments to a new process. Arguments property was not removed for backward compat reasons.

    So instead of:

    var builder = new StringBuilder();
    builder.Append(myAlreadyEscapedArgumentsComingFromElsewhere);
    foreach (var arg in listOfUnescapedArguments)
    {
        builder.Append(ProcessStartInfo.EscapeArgument(arg));
    }
    info.Arguments = builder.ToString(); 

    The users can forget about escaping and just provide the args:

    foreach (var arg in listOfUnescapedArguments)
    {
        info.ArgumentList.Add(arg);
    }

    And in your case you have some pre-concatenated string with some escaped args and you would like to add some more to it?

  5. removed
    untriagedNew issue has not been triaged by the area owner
    on Aug 29, 2025
  6. added this to the Future milestone on Aug 29, 2025
  7. Youssef1313 commented on Aug 29, 2025

    @Youssef1313
    MemberAuthor

    And in your case you have some pre-concatenated string with some escaped args and you would like to add some more to it?

    Yes. In my case I have already a single string that is properly escaped already. So I think an alternative is to provide an API to "unescape" it, then use ArgumentList?

  8. adamsitnik commented on Aug 29, 2025

    @adamsitnik
    Member

    So I think an alternative is to provide an API to "unescape" it, then use ArgumentList?

    System.CommandLine (already used by the SDK) provides an API for that:

    https://github.com/dotnet/command-line-api/blob/fab13a397461f4ff16b988ba96cb08891ac75257/src/System.CommandLine/Parsing/CommandLineParser.cs#L40

    This test shows how it works: https://github.com/dotnet/command-line-api/blob/fab13a397461f4ff16b988ba96cb08891ac75257/src/System.CommandLine.Tests/SplitCommandLineTests.cs#L36-L41

    But back to your original request for now I am hesitant of adding such API. You are the first user asking for it since ArgumentList was added in .NET Core 2.1 (8 years ago?) I would prefer to wait and get more up votes/feedback for a while

  9. KalleOlaviNiemitalo commented on Aug 29, 2025

    @KalleOlaviNiemitalo

    CommandLineParser.SplitCommandLine(string commandLine) matches neither CommandLineToArgvW nor POSIX sh word splitting.

    From where do you get the "single string that is properly escaped already": is it built by some API, or read from a file edited by a user?

  10. Youssef1313 commented on Aug 29, 2025

    @Youssef1313
    MemberAuthor

    @KalleOlaviNiemitalo For the case of SDK, that's RunArguments MSBuild property (coming from user)

  11. jkotas commented on Aug 29, 2025

    @jkotas
    Member

    Related: #668

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions