diff --git a/src/BenchmarkDotNet/Jobs/Argument.cs b/src/BenchmarkDotNet/Jobs/Argument.cs index c86c83906a..6ec416c8e7 100644 --- a/src/BenchmarkDotNet/Jobs/Argument.cs +++ b/src/BenchmarkDotNet/Jobs/Argument.cs @@ -45,8 +45,34 @@ public MonoArgument(string value) : base(value) /// example: new MsBuildArgument("/p:MyCustomSetting=123") /// [PublicAPI] + + /// + /// A specialized MSBuild argument that sets a property using a quoted, semicolon-separated list of values. + /// + public class MsBuildProperty : MsBuildArgument + { + public MsBuildProperty(string key, params string[] values) + : base($"/p:{key}=\"{string.Join(";", values)}") + { + } + + + } public class MsBuildArgument : Argument { public MsBuildArgument(string value) : base(value) { } + + public MsBuildArgument(string key, params string[] values) + : base($"/p:{key}={EscapeAndJoin(values)}") { } + + private static string EscapeAndJoin(string[] values) + { + return string.Join("%3b", values.Select(EscapeSpecialChars)); + } + + private static string EscapeSpecialChars(string input) + { + return input.Replace(";", "%3B"); + } } } \ No newline at end of file diff --git a/tests/BenchmarkDotNet.IntegrationTests.ManualRunning/MsBuildArgumentTests.cs b/tests/BenchmarkDotNet.IntegrationTests.ManualRunning/MsBuildArgumentTests.cs index f4619040cc..22c346ec2d 100644 --- a/tests/BenchmarkDotNet.IntegrationTests.ManualRunning/MsBuildArgumentTests.cs +++ b/tests/BenchmarkDotNet.IntegrationTests.ManualRunning/MsBuildArgumentTests.cs @@ -24,6 +24,13 @@ public void ProcessIsBuiltWithCustomProperty(bool setCustomProperty) CanExecute(config); } + [Fact] + + public void MsBuildProperty_ShouldWrapMultipleValuesInQuotes() + { + var arg = new MsBuildProperty("DefineConstants", "FOO", "BAR"); + Assert.Equal("/p:DefineConstants=\"FOO;BAR\"", arg.TextRepresentation); + } [Fact] public void MultipleProcessesAreBuiltWithCorrectProperties() {