Skip to content

Commit fa1a4f5

Browse files
authored
Fix Pester CodeLens run/debug by not quoting params/already quoted args (#794)
* Fix Pester CodeLens run/debug by not quoting params/already quoted args Requires a corresponding PR in vscode-powershell. We should look this one over good as it has potential to break folks. I think the odds are low. Essentially we added the QuoteEscapString method because we get raw paths from VSCode when debugging the current file. Those paths are quoted because they may contain spaces and because we use single quotes, existing single quotes have to be doubled e.g C:\Don'tUseQuotesInPaths to 'C:\Don''tUseQuotesInPaths'. This unfortunately was always being invoked on args. Now we check if the arg is a parameter (starts with '-') or is already quoted. The thinking is if the users is specifying a quoted arg, it's on them to handle any necessary escaping. BTW is there another char that can act as the start of a parameter - like the longer dash - whatever that is called. Longer term, we need a better solution for how to handle paths from VSCode. Maybe we handle them there and eliminate the escaping logic in PSES? * Revert to not escape/quoting args or script value when not a file path
1 parent 19d5c5b commit fa1a4f5

File tree

2 files changed

+23
-19
lines changed

2 files changed

+23
-19
lines changed

src/PowerShellEditorServices.Protocol/Server/DebugAdapter.cs

+1-10
Original file line numberDiff line numberDiff line change
@@ -302,16 +302,7 @@ protected async Task HandleLaunchRequest(
302302
string arguments = null;
303303
if ((launchParams.Args != null) && (launchParams.Args.Length > 0))
304304
{
305-
var sb = new StringBuilder();
306-
for (int i = 0; i < launchParams.Args.Length; i++)
307-
{
308-
sb.Append(PowerShellContext.QuoteEscapeString(launchParams.Args[i]));
309-
if (i < launchParams.Args.Length - 1)
310-
{
311-
sb.Append(' ');
312-
}
313-
}
314-
arguments = sb.ToString();
305+
arguments = string.Join(" ", launchParams.Args);
315306
Logger.Write(LogLevel.Verbose, "Script arguments are: " + arguments);
316307
}
317308

src/PowerShellEditorServices/Session/PowerShellContext.cs

+22-9
Original file line numberDiff line numberDiff line change
@@ -769,7 +769,6 @@ await this.ExecuteCommand<object>(
769769
/// <returns>A Task that can be awaited for completion.</returns>
770770
public async Task ExecuteScriptWithArgs(string script, string arguments = null, bool writeInputToHost = false)
771771
{
772-
var escapedScriptPath = new StringBuilder(PowerShellContext.WildcardEscapePath(script));
773772
PSCommand command = new PSCommand();
774773

775774
if (arguments != null)
@@ -791,24 +790,38 @@ public async Task ExecuteScriptWithArgs(string script, string arguments = null,
791790
"Could not determine current filesystem location:\r\n\r\n" + e.ToString());
792791
}
793792

794-
// If we don't escape wildcard characters in a path to a script file, the script can
795-
// fail to execute if say the script filename was foo][.ps1.
793+
var strBld = new StringBuilder();
794+
795+
// The script parameter can refer to either a "script path" or a "command name". If it is a
796+
// script path, we can determine that by seeing if the path exists. If so, we always single
797+
// quote that path in case it includes special PowerShell characters like ', &, (, ), [, ] and
798+
// <space>. Any embedded single quotes are escaped.
799+
// If the provided path is already quoted, then File.Exists will not find it.
800+
// This keeps us from quoting an already quoted path.
796801
// Related to issue #123.
797802
if (File.Exists(script) || File.Exists(scriptAbsPath))
798803
{
799-
// Dot-source the launched script path
800-
string escapedFilePath = escapedScriptPath.ToString();
801-
escapedScriptPath = new StringBuilder(". ").Append(QuoteEscapeString(escapedFilePath));
804+
// Dot-source the launched script path and single quote the path in case it includes
805+
strBld.Append(". ").Append(QuoteEscapeString(script));
806+
}
807+
else
808+
{
809+
strBld.Append(script);
802810
}
803811

804812
// Add arguments
805-
escapedScriptPath.Append(' ').Append(arguments);
813+
strBld.Append(' ').Append(arguments);
814+
815+
var launchedScript = strBld.ToString();
816+
this.logger.Write(LogLevel.Verbose, $"Launch script is: {launchedScript}");
806817

807-
command.AddScript(escapedScriptPath.ToString(), false);
818+
command.AddScript(launchedScript, false);
808819
}
809820
else
810821
{
811-
command.AddCommand(escapedScriptPath.ToString(), false);
822+
// AddCommand can handle script paths including those with special chars e.g.:
823+
// ".\foo & [bar]\foo.ps1" and it can handle arbitrary commands, like "Invoke-Pester"
824+
command.AddCommand(script, false);
812825
}
813826

814827
if (writeInputToHost)

0 commit comments

Comments
 (0)