diff --git a/src/ArgumentBuilder.cs b/src/ArgumentBuilder.cs index 75bf927..01390b4 100644 --- a/src/ArgumentBuilder.cs +++ b/src/ArgumentBuilder.cs @@ -50,6 +50,35 @@ public static string EscapeAndConcatenateCommandAndArgArrayForProcessStart( return sb.ToString(); } + /// + /// Undo the processing which took place to create string[] args in Main, so that the next process will receive the same string[] args. + /// + /// + /// Note that pwsh does not require any special escaping of arguments. We can simply concatenate the list of strings with a space between each. + /// + /// The base command. + /// List of arguments to escape. + /// An escaped string of the and . + public static string ConcatenateCommandAndArgArrayForPwshProcessStart( + string? command, + string[]? args) + { + var sb = new ValueStringBuilder(stackalloc char[256]); + + sb.Append(command); + + if (args is not null) + { + for (var i = 0; i < args.Length; i++) + { + sb.Append(Space); + sb.Append(args[i]); + } + } + + return sb.ToString(); + } + /// /// Undo the processing which took place to create string[] args in Main, so that the next process will receive the same string[] args. /// diff --git a/src/CommandRunner.cs b/src/CommandRunner.cs index 965c3bd..07e752d 100644 --- a/src/CommandRunner.cs +++ b/src/CommandRunner.cs @@ -56,6 +56,11 @@ public async Task RunAsync(string name, string cmd, string[]? args) ArgumentBuilder.EscapeAndConcatenateCommandAndArgArrayForCmdProcessStart(cmd, args), "\""); } + else if (_processContext.Shell.Equals("pwsh", StringComparison.OrdinalIgnoreCase)) + { + process.StartInfo.ArgumentList.Add("-c"); + process.StartInfo.ArgumentList.Add(ArgumentBuilder.ConcatenateCommandAndArgArrayForPwshProcessStart(cmd, args)); + } else { process.StartInfo.ArgumentList.Add("-c"); diff --git a/test/ArgumentBuilderTests.cs b/test/ArgumentBuilderTests.cs index b95e3b7..5d9c6ce 100644 --- a/test/ArgumentBuilderTests.cs +++ b/test/ArgumentBuilderTests.cs @@ -27,6 +27,29 @@ public void EscapeAndConcatenateCommandAndArgArrayForProcessStart(string command result.ShouldBe(expected); } + [Theory] + [InlineData("pwsh", null, "pwsh")] + [InlineData("pws \"h\"", null, "pws \"h\"")] + [InlineData("p w s h", null, "p w s h")] + [InlineData("pwsh", new string[0], "pwsh")] + [InlineData("pwsh", new[] { "one", "two", "three" }, "pwsh one two three")] + [InlineData("pwsh", new[] { "line1\nline2", "word1\tword2" }, "pwsh line1\nline2 word1\tword2")] + [InlineData("pwsh", new[] { "with spaces" }, "pwsh with spaces")] + [InlineData("pwsh", new[] { @"with\backslash" }, @"pwsh with\backslash")] + [InlineData("pwsh", new[] { @"""quotedwith\backslash""" }, @"pwsh ""quotedwith\backslash""" )] + [InlineData("pwsh", new[] { @"C:\Users\" }, @"pwsh C:\Users\")] + [InlineData("pwsh", new[] { @"C:\Program Files\dotnet\" }, @"pwsh C:\Program Files\dotnet\")] + [InlineData("pwsh", new[] { @"backslash\""preceedingquote" }, @"pwsh backslash\""preceedingquote")] + [InlineData("pwsh", new[] { @""" hello """ }, @"pwsh "" hello """)] + public void ConcatenateCommandAndArgArrayForPwshProcessStart(string command, string[]? args, string expected) + { + // Given / When + var result = ArgumentBuilder.ConcatenateCommandAndArgArrayForPwshProcessStart(command, args); + + // Then + result.ShouldBe(expected); + } + [Theory] [InlineData("cmd", null, "cmd")] [InlineData("cm \"d\"", null, "cm \"d\"")]