diff --git a/src/Microsoft.DotNet.Cli.Utils/ArgumentEscaper.cs b/src/Microsoft.DotNet.Cli.Utils/ArgumentEscaper.cs index 79ab2aa1c..afaa58d48 100644 --- a/src/Microsoft.DotNet.Cli.Utils/ArgumentEscaper.cs +++ b/src/Microsoft.DotNet.Cli.Utils/ArgumentEscaper.cs @@ -185,12 +185,6 @@ namespace Microsoft.DotNet.Cli.Utils internal static bool ShouldSurroundWithQuotes(string argument) { - // Don't quote already quoted strings - if (IsSurroundedWithQuotes(argument)) - { - return false; - } - // Only quote if whitespace exists in the string return ArgumentContainsWhitespace(argument); } diff --git a/src/Microsoft.DotNet.Cli.Utils/CommandResolution/WindowsExePreferredCommandSpecFactory.cs b/src/Microsoft.DotNet.Cli.Utils/CommandResolution/WindowsExePreferredCommandSpecFactory.cs index 7815c77f0..4c5940c7a 100644 --- a/src/Microsoft.DotNet.Cli.Utils/CommandResolution/WindowsExePreferredCommandSpecFactory.cs +++ b/src/Microsoft.DotNet.Cli.Utils/CommandResolution/WindowsExePreferredCommandSpecFactory.cs @@ -63,7 +63,8 @@ namespace Microsoft.DotNet.Cli.Utils var cmdEscapedArgs = ArgumentEscaper.EscapeAndConcatenateArgArrayForCmdProcessStart(args); - if (ArgumentEscaper.ShouldSurroundWithQuotes(command)) + if (!ArgumentEscaper.IsSurroundedWithQuotes(command) // Don't quote already quoted strings + && ArgumentEscaper.ShouldSurroundWithQuotes(command)) { command = $"\"{command}\""; } diff --git a/test/Microsoft.DotNet.Cli.Utils.Tests/ArgumentEscaperTests.cs b/test/Microsoft.DotNet.Cli.Utils.Tests/ArgumentEscaperTests.cs new file mode 100644 index 000000000..92ae9df36 --- /dev/null +++ b/test/Microsoft.DotNet.Cli.Utils.Tests/ArgumentEscaperTests.cs @@ -0,0 +1,25 @@ +// Copyright (c) .NET Foundation and contributors. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +using Xunit; + +namespace Microsoft.DotNet.Cli.Utils.Tests +{ + public class ArgumentEscaperTests + { + [Theory] + [InlineData(new[] { "one", "two", "three" }, "one two three")] + [InlineData(new[] { "line1\nline2", "word1\tword2" }, "\"line1\nline2\" \"word1\tword2\"")] + [InlineData(new[] { "with spaces" }, "\"with spaces\"")] + [InlineData(new[] { @"with\backslash" }, @"with\backslash")] + [InlineData(new[] { @"""quotedwith\backslash""" }, @"\""quotedwith\backslash\""")] + [InlineData(new[] { @"C:\Users\" }, @"C:\Users\")] + [InlineData(new[] { @"C:\Program Files\dotnet\" }, @"""C:\Program Files\dotnet\\""")] + [InlineData(new[] { @"backslash\""preceedingquote" }, @"backslash\\\""preceedingquote")] + [InlineData(new[] { @""" hello """ }, @"""\"" hello \""""")] + public void EscapesArgumentsForProcessStart(string[] args, string expected) + { + Assert.Equal(expected, ArgumentEscaper.EscapeAndConcatenateArgArrayForProcessStart(args)); + } + } +}