Skip to content

Commit b6f58e9

Browse files
committed
More work on #149. Need to be able to unescape paths as well as escape the.
The trick is to unescape paths coming from VSCode as the user may have decided to escape spaces and [ and ]. .NET APIs won't handle those paths. So we unescape them and cache them in Workspace.cs. Later, just before we call down to the PowerShell engine to do work that requires the script path, we escape those paths appropriately for PowerShell.
1 parent ab1e555 commit b6f58e9

File tree

3 files changed

+29
-3
lines changed

3 files changed

+29
-3
lines changed

src/PowerShellEditorServices/Session/PowerShellContext.cs

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
using System.Collections.ObjectModel;
1313
using System.Linq;
1414
using System.Text;
15+
using System.Text.RegularExpressions;
1516
using System.Threading;
1617
using System.Threading.Tasks;
1718

@@ -584,16 +585,33 @@ internal void ReleaseRunspaceHandle(RunspaceHandle runspaceHandle)
584585
/// <returns>The path with [ and ] escaped.</returns>
585586
internal static string EscapePath(string path, bool escapeSpaces)
586587
{
587-
string escapedPath = path.Replace("[", "`[").Replace("]", "`]");
588+
string escapedPath = Regex.Replace(path, @"(?<!`)\[", "`[");
589+
escapedPath = Regex.Replace(escapedPath, @"(?<!`)\]", "`]");
588590

589591
if (escapeSpaces)
590592
{
591-
escapedPath = escapedPath.Replace(" ", "` ");
593+
escapedPath = Regex.Replace(escapedPath, @"(?<!`) ", "` ");
592594
}
593595

594596
return escapedPath;
595597
}
596598

599+
/// <summary>
600+
/// Unescapes any escaped [, ] or space characters. Typically use this before calling a
601+
/// .NET API that doesn't understand PowerShell escaped chars.
602+
/// </summary>
603+
/// <param name="path">The path to unescape.</param>
604+
/// <returns>The path with the ` character before [, ] and spaces removed.</returns>
605+
internal static string UnescapePath(string path)
606+
{
607+
if (!path.Contains("`"))
608+
{
609+
return path;
610+
}
611+
612+
return Regex.Replace(path, @"`(?=[ \[\]])", "");
613+
}
614+
597615
#endregion
598616

599617
#region Events

src/PowerShellEditorServices/Workspace/Workspace.cs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -210,6 +210,11 @@ private string ResolveFilePath(string filePath)
210210
// Some clients send paths with UNIX-style slashes, replace those if necessary
211211
filePath = filePath.Replace('/', '\\');
212212

213+
// Clients could specify paths with escaped space, [ and ] characters which .NET APIs
214+
// will not handle. These paths will get appropriately escaped just before being passed
215+
// into the PowerShell engine.
216+
filePath = PowerShellContext.UnescapePath(filePath);
217+
213218
// Get the absolute file path
214219
filePath = Path.GetFullPath(filePath);
215220
}

test/PowerShellEditorServices.Test/Debugging/DebugServiceTests.cs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,9 +87,12 @@ public static IEnumerable<object[]> DebuggerAcceptsScriptArgsTestData
8787
[MemberData("DebuggerAcceptsScriptArgsTestData")]
8888
public async Task DebuggerAcceptsScriptArgs(string[] args)
8989
{
90+
// The path is intentionally odd (some escaped chars but not all) because we are testing
91+
// the internal path escaping mechanism - it should escape certains chars ([, ] and space) but
92+
// it should not escape already escaped chars.
9093
ScriptFile debugWithParamsFile =
9194
this.workspace.GetFile(
92-
@"..\..\..\PowerShellEditorServices.Test.Shared\Debugging\Debug With Params [Test].ps1");
95+
@"..\..\..\PowerShellEditorServices.Test.Shared\Debugging\Debug` With Params `[Test].ps1");
9396

9497
await this.debugService.SetBreakpoints(
9598
debugWithParamsFile,

0 commit comments

Comments
 (0)