Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Auto-escape MSBuild special characters in MsBuildArgument #2729

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
Gal-lankri wants to merge 3 commits into dotnet:master
base: master
Choose a base branch
Loading
from Gal-lankri:feature/msbuild-escape

Conversation

Copy link

@Gal-lankri Gal-lankri commented May 13, 2025

Summary

This PR adds automatic escaping of MSBuild-reserved characters in the MsBuildArgument class (e.g., ;, %, $, @, etc.), so users no longer need to manually encode these characters when passing MSBuild parameters.

Why

Previously, developers had to encode characters like semicolons manually (;%3B). This PR improves usability and correctness when passing multiple values to MSBuild properties such as DefineConstants.

Changes

  • Updated MsBuildArgument constructor to auto-escape special characters
  • Added a [Theory]-based test (EscapesSpecialCharactersCorrectly) to cover:
    • Semicolons
    • Percent
    • Dollar sign
    • At-symbol
    • Parentheses
    • Asterisk
    • Normal input (no escape)

Example

new MsBuildArgument("/p:DefineConstants=DEBUG;TRACE")
// becomes:
"/p:DefineConstants=DEBUG%3BTRACE"

Copy link
Author

@dotnet-policy-service agree

Copy link
Collaborator

timcassell commented May 13, 2025
edited
Loading

@Gal-lankri (削除) Can you please pull latest upstream master to your fork and rebase your branch? Github is picking up a lot of unrelated changes. (削除ここまで) [Edit] Or explain why <Platforms>AnyCPU;x64</Platforms> was added to all the projects?

Copy link
Author

@timcassell sorry that's was by mistake. I will fix that.

public MsBuildArgument(string value) : base(value) { }
private static readonly Dictionary<char, string> MsBuildEscapes = new ()
{
{ '%', "%25" },
Copy link
Collaborator

@timcassell timcassell May 14, 2025

Choose a reason for hiding this comment

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

If anyone has already escaped their arguments, this will break them. Is there a way to avoid any breaks?

Copy link
Author

@Gal-lankri Gal-lankri May 14, 2025

Choose a reason for hiding this comment

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

Great point — thanks for flagging that!

You're absolutely right: blindly escaping everything could break cases where users already passed escaped values like %3B or %25.

To handle this safely, I updated the implementation to:

  • Detect and preserve only escape sequences that match known MSBuild-escaped values (like %3B, %24, etc.)
  • This prevents double-escaping for cases where users already encoded special characters, while still escaping unescaped input correctly

Additionally, if preferred, I can also add a bool alreadyEscaped = false parameter to the MsBuildArgument constructor. That way:

  • Power users can bypass escaping entirely if they know their input is already safe
  • Default behavior remains user-friendly for most use cases

Let me know if you'd prefer we add that constructor overload as well. Happy to follow up with it!

Copy link
Collaborator

@timcassell timcassell May 14, 2025
edited
Loading

Choose a reason for hiding this comment

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

It can get weird if someone puts 100%25, it's ambiguous to us whether it should be 100% or 100%25. I think it would be better to add a bool escapeSpecialChars = true param (or false default to preserve existing behavior), and don't try to parse for existing escapes.

Copy link
Author

@Gal-lankri Gal-lankri May 14, 2025

Choose a reason for hiding this comment

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

Yes, good point, thank you!

You're right, there's no reliable way to guess the user's intent in edge cases like 100%25. Maybe it's smarter to let the user to decide.

I've updated the implementation to:

  • Add a bool escapeSpecialChars = true parameter to the MsBuildArgument constructor
  • If true, the value is escaped
  • If false, the value is passed through exactly as provided (for pre-escaped input)

This avoids ambiguity and doesn't change the default behavior for existing users.

Copy link
Contributor

filzrev commented May 15, 2025

This issue is tracked by #2719 also.

I though it's better to separate MSBuildArgument's TextRepresentation with argument that is used inside .bat/.sh files.
https://github.com/dotnet/BenchmarkDotNet/blob/v0.14.0/src/BenchmarkDotNet/Toolchains/DotNetCli/DotNetCliCommand.cs#L203C72-L203C90.

Because TextRepresentation is shown on Argument column on benchmark report and it's hard to read if contains escape chars.

Additionally, It seems escape is needed when passing MSBuild parameter with -p:{key}={value} and -rp:{key}={value} format.
As far as I've confirmed, Other msbuild command argument works without escaping (e.g. -getProperty:Prop1;Prop2)

timcassell reacted with thumbs up emoji

Copy link
Collaborator

timcassell commented May 15, 2025
edited
Loading

Because TextRepresentation is shown on Argument column on benchmark report and it's hard to read if contains escape chars.

That's a good point. MsBuildArgument can override ToString to display the original value (or add another internal method to get the escaped value, which I think is what you were getting at).

Additionally, It seems escape is needed when passing MSBuild parameter with -p:{key}={value} and -rp:{key}={value} format. As far as I've confirmed, Other msbuild command argument works without escaping (e.g. -getProperty:Prop1;Prop2)

Seems like a good reason to not escape by default. Users should opt-in rather than opt-out.

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

Reviewers

@timcassell timcassell timcassell left review comments

Assignees

No one assigned

Labels

None yet

Projects

None yet

Milestone

No milestone

Development

Successfully merging this pull request may close these issues.

Feature Request: Add MsBuildArgument supports for MSBuild special characters

AltStyle によって変換されたページ (->オリジナル) /