diff --git a/src/System.Management.Automation/engine/NativeCommandParameterBinder.cs b/src/System.Management.Automation/engine/NativeCommandParameterBinder.cs index c00f62823e..44c298c776 100644 --- a/src/System.Management.Automation/engine/NativeCommandParameterBinder.cs +++ b/src/System.Management.Automation/engine/NativeCommandParameterBinder.cs @@ -196,7 +196,13 @@ namespace System.Management.Automation if (NeedQuotes(arg)) { _arguments.Append('"'); + // need to escape all trailing backslashes so the native command receives it correctly + // according to http://www.daviddeley.com/autohotkey/parameters/parameters.htm#WINCRULESDOC _arguments.Append(arg); + for (int i = arg.Length-1; i >= 0 && arg[i] == '\\'; i--) + { + _arguments.Append('\\'); + } _arguments.Append('"'); } else diff --git a/test/powershell/Language/Scripting/NativeExecution/NativeCommandArguments.Tests.ps1 b/test/powershell/Language/Scripting/NativeExecution/NativeCommandArguments.Tests.ps1 index aba3637c03..aaa82eb40c 100644 --- a/test/powershell/Language/Scripting/NativeExecution/NativeCommandArguments.Tests.ps1 +++ b/test/powershell/Language/Scripting/NativeExecution/NativeCommandArguments.Tests.ps1 @@ -8,7 +8,7 @@ Describe "Native Command Arguments" -tags "CI" { It "Should handle quoted spaces correctly" { $a = 'a"b c"d' $lines = testexe -echoargs $a 'a"b c"d' a"b c"d - ($lines | measure).Count | Should Be 3 + $lines.Count | Should Be 3 $lines[0] | Should Be 'Arg 0 is ' $lines[1] | Should Be 'Arg 1 is ' $lines[2] | Should Be 'Arg 2 is ' @@ -27,8 +27,20 @@ Describe "Native Command Arguments" -tags "CI" { # looking at how it got the arguments. It "Should handle spaces between escaped quotes" { $lines = testexe -echoargs 'a\"b c\"d' "a\`"b c\`"d" - ($lines | measure).Count | Should Be 2 + $lines.Count | Should Be 2 $lines[0] | Should Be 'Arg 0 is ' $lines[1] | Should Be 'Arg 1 is ' } + + It "Should correctly quote paths with spaces: " -TestCases @( + @{arguments = "'.\test 1\' `".\test 2\`"" ; expected = @(".\test 1\",".\test 2\")}, + @{arguments = "'.\test 1\\\' `".\test 2\\`""; expected = @(".\test 1\\\",".\test 2\\")} + ) { + param($arguments, $expected) + $lines = Invoke-Expression "testexe -echoargs $arguments" + $lines.Count | Should Be $expected.Count + for ($i = 0; $i -lt $lines.Count; $i++) { + $lines[$i] | Should Be "Arg $i is <$($expected[$i])>" + } + } }