Skip to content

Commit 7ed401e

Browse files
committed
Modify ExecuteScriptAtPath to handle arb script.
Renamed to ExecuteScriptWithArgs and check if "script" is a filename before attempting to escape wildcard chars in path.
1 parent 2aa8087 commit 7ed401e

File tree

4 files changed

+55
-34
lines changed

4 files changed

+55
-34
lines changed

src/PowerShellEditorServices.Protocol/Server/DebugAdapter.cs

+15-15
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ public class DebugAdapter : DebugAdapterBase
2727

2828
private bool noDebug;
2929
private bool waitingForAttach;
30-
private string scriptPathToLaunch;
30+
private string scriptToLaunch;
3131
private string arguments;
3232

3333
public DebugAdapter(HostDetails hostDetails, ProfilePaths profilePaths)
@@ -83,7 +83,7 @@ protected override void Initialize()
8383
protected Task LaunchScript(RequestContext<object> requestContext)
8484
{
8585
return editorSession.PowerShellContext
86-
.ExecuteScriptAtPath(this.scriptPathToLaunch, this.arguments)
86+
.ExecuteScriptWithArgs(this.scriptToLaunch, this.arguments)
8787
.ContinueWith(
8888
async (t) => {
8989
Logger.Write(LogLevel.Verbose, "Execution completed, flushing output then terminating...");
@@ -120,7 +120,7 @@ protected async Task HandleConfigurationDoneRequest(
120120
object args,
121121
RequestContext<object> requestContext)
122122
{
123-
if (!string.IsNullOrEmpty(this.scriptPathToLaunch))
123+
if (!string.IsNullOrEmpty(this.scriptToLaunch))
124124
{
125125
if (this.editorSession.PowerShellContext.SessionState == PowerShellContextState.Ready)
126126
{
@@ -144,8 +144,8 @@ protected async Task HandleLaunchRequest(
144144
LaunchRequestArguments launchParams,
145145
RequestContext<object> requestContext)
146146
{
147-
// Set the working directory for the PowerShell runspace to the cwd passed in via launch.json.
148-
// In case that is null, use the the folder of the script to be executed. If the resulting
147+
// Set the working directory for the PowerShell runspace to the cwd passed in via launch.json.
148+
// In case that is null, use the the folder of the script to be executed. If the resulting
149149
// working dir path is a file path then extract the directory and use that.
150150
string workingDir =
151151
launchParams.Cwd ??
@@ -195,15 +195,15 @@ protected async Task HandleLaunchRequest(
195195
// Store the launch parameters so that they can be used later
196196
this.noDebug = launchParams.NoDebug;
197197
#pragma warning disable 618
198-
this.scriptPathToLaunch = launchParams.Script ?? launchParams.Program;
198+
this.scriptToLaunch = launchParams.Script ?? launchParams.Program;
199199
#pragma warning restore 618
200200
this.arguments = arguments;
201201

202202
await requestContext.SendResult(null);
203203

204204
// If no script is being launched, execute an empty script to
205205
// cause the prompt string to be evaluated and displayed
206-
if (string.IsNullOrEmpty(this.scriptPathToLaunch))
206+
if (string.IsNullOrEmpty(this.scriptToLaunch))
207207
{
208208
await this.editorSession.PowerShellContext.ExecuteScriptString(
209209
"", false, true);
@@ -222,7 +222,7 @@ protected async Task HandleAttachRequest(
222222
{
223223
// If there are no host processes to attach to or the user cancels selection, we get a null for the process id.
224224
// This is not an error, just a request to stop the original "attach to" request.
225-
// Testing against "undefined" is a HACK because I don't know how to make "Cancel" on quick pick loading
225+
// Testing against "undefined" is a HACK because I don't know how to make "Cancel" on quick pick loading
226226
// to cancel on the VSCode side without sending an attachRequest with processId set to "undefined".
227227
if (string.IsNullOrEmpty(attachParams.ProcessId) || (attachParams.ProcessId == "undefined"))
228228
{
@@ -364,7 +364,7 @@ protected async Task HandleSetBreakpointsRequest(
364364
catch (Exception e) when (e is FileNotFoundException || e is DirectoryNotFoundException)
365365
{
366366
Logger.Write(
367-
LogLevel.Warning,
367+
LogLevel.Warning,
368368
$"Attempted to set breakpoints on a non-existing file: {setBreakpointsParams.Source.Path}");
369369

370370
string message = this.noDebug ? string.Empty : "Source does not exist, breakpoint not set.";
@@ -387,9 +387,9 @@ await requestContext.SendResult(
387387
{
388388
SourceBreakpoint srcBreakpoint = setBreakpointsParams.Breakpoints[i];
389389
breakpointDetails[i] = BreakpointDetails.Create(
390-
scriptFile.FilePath,
391-
srcBreakpoint.Line,
392-
srcBreakpoint.Column,
390+
scriptFile.FilePath,
391+
srcBreakpoint.Line,
392+
srcBreakpoint.Column,
393393
srcBreakpoint.Condition,
394394
srcBreakpoint.HitCondition);
395395
}
@@ -541,7 +541,7 @@ protected async Task HandleStackTraceRequest(
541541
// be referenced back to the current list of stack frames
542542
newStackFrames.Add(
543543
StackFrame.Create(
544-
stackFrames[i],
544+
stackFrames[i],
545545
i));
546546
}
547547

@@ -712,9 +712,9 @@ async void DebugService_DebuggerStopped(object sender, DebuggerStoppedEventArgs
712712

713713
// Provide the reason for why the debugger has stopped script execution.
714714
// See https://github.com/Microsoft/vscode/issues/3648
715-
// The reason is displayed in the breakpoints viewlet. Some recommended reasons are:
715+
// The reason is displayed in the breakpoints viewlet. Some recommended reasons are:
716716
// "step", "breakpoint", "function breakpoint", "exception" and "pause".
717-
// We don't support exception breakpoints and for "pause", we can't distinguish
717+
// We don't support exception breakpoints and for "pause", we can't distinguish
718718
// between stepping and the user pressing the pause/break button in the debug toolbar.
719719
string debuggerStoppedReason = "step";
720720
if (e.OriginalEvent.Breakpoints.Count > 0)

src/PowerShellEditorServices/Session/PowerShellContext.cs

+28-7
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
using System.Globalization;
1010
using System.Collections.Generic;
1111
using System.Collections.ObjectModel;
12+
using System.IO;
1213
using System.Linq;
1314
using System.Text;
1415
using System.Text.RegularExpressions;
@@ -625,26 +626,46 @@ await this.ExecuteCommand<object>(
625626
/// <summary>
626627
/// Executes a script file at the specified path.
627628
/// </summary>
628-
/// <param name="scriptPath">The path to the script file to execute.</param>
629+
/// <param name="script">The script execute.</param>
629630
/// <param name="arguments">Arguments to pass to the script.</param>
630631
/// <returns>A Task that can be awaited for completion.</returns>
631-
public async Task ExecuteScriptAtPath(string scriptPath, string arguments = null)
632+
public async Task ExecuteScriptWithArgs(string script, string arguments = null)
632633
{
633634
PSCommand command = new PSCommand();
634635

635636
if (arguments != null)
636637
{
637-
// If we don't escape wildcard characters in the script path, the script can
638-
// fail to execute if say the script name was foo][.ps1.
638+
// Need to determine If the script string is a path to a script file.
639+
string scriptAbsPath = string.Empty;
640+
try
641+
{
642+
// Assume we can only debug scripts from the FileSystem provider
643+
string workingDir =
644+
this.CurrentRunspace.Runspace.SessionStateProxy.Path.CurrentFileSystemLocation.ProviderPath;
645+
workingDir = workingDir.TrimEnd(Path.DirectorySeparatorChar);
646+
scriptAbsPath = workingDir + Path.DirectorySeparatorChar + script;
647+
}
648+
catch (System.Management.Automation.DriveNotFoundException e)
649+
{
650+
Logger.Write(
651+
LogLevel.Error,
652+
"Could not determine current filesystem location:\r\n\r\n" + e.ToString());
653+
}
654+
655+
// If we don't escape wildcard characters in a path to a script file, the script can
656+
// fail to execute if say the script filename was foo][.ps1.
639657
// Related to issue #123.
640-
string escapedScriptPath = EscapePath(scriptPath, escapeSpaces: true);
641-
string scriptWithArgs = escapedScriptPath + " " + arguments;
658+
if (File.Exists(script) || File.Exists(scriptAbsPath))
659+
{
660+
script = EscapePath(script, escapeSpaces: true);
661+
}
642662

663+
string scriptWithArgs = script + " " + arguments;
643664
command.AddScript(scriptWithArgs);
644665
}
645666
else
646667
{
647-
command.AddCommand(scriptPath);
668+
command.AddCommand(script);
648669
}
649670

650671
await this.ExecuteCommand<object>(command, true);

test/PowerShellEditorServices.Test/Debugging/DebugServiceTests.cs

+10-10
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,7 @@ await this.debugService.SetLineBreakpoints(
113113

114114
// Execute the script and wait for the breakpoint to be hit
115115
Task executeTask =
116-
this.powerShellContext.ExecuteScriptAtPath(
116+
this.powerShellContext.ExecuteScriptWithArgs(
117117
debugWithParamsFile.FilePath, arguments);
118118

119119
await this.AssertDebuggerStopped(debugWithParamsFile.FilePath);
@@ -131,7 +131,7 @@ await this.debugService.SetLineBreakpoints(
131131
var = variables.FirstOrDefault(v => v.Name == "$Param2");
132132
Assert.NotNull(var);
133133
Assert.True(var.IsExpandable);
134-
134+
135135
var childVars = debugService.GetVariables(var.Id);
136136
Assert.Equal(9, childVars.Length);
137137
Assert.Equal("\"Bar\"", childVars[0].ValueString);
@@ -194,7 +194,7 @@ await this.debugService.SetCommandBreakpoints(
194194
await this.AssertStateChange(PowerShellContextState.Ready);
195195

196196
Task executeTask =
197-
this.powerShellContext.ExecuteScriptAtPath(
197+
this.powerShellContext.ExecuteScriptWithArgs(
198198
this.debugScriptFile.FilePath);
199199

200200
// Wait for function breakpoint to hit
@@ -273,7 +273,7 @@ await this.debugService.SetLineBreakpoints(
273273
await this.AssertStateChange(PowerShellContextState.Ready);
274274

275275
Task executeTask =
276-
this.powerShellContext.ExecuteScriptAtPath(
276+
this.powerShellContext.ExecuteScriptWithArgs(
277277
this.debugScriptFile.FilePath);
278278

279279
// Wait for a couple breakpoints
@@ -303,7 +303,7 @@ await this.debugService.SetLineBreakpoints(
303303
await this.AssertStateChange(PowerShellContextState.Ready);
304304

305305
Task executeTask =
306-
this.powerShellContext.ExecuteScriptAtPath(
306+
this.powerShellContext.ExecuteScriptWithArgs(
307307
this.debugScriptFile.FilePath);
308308

309309
// Wait for conditional breakpoint to hit
@@ -353,7 +353,7 @@ await this.debugService.SetLineBreakpoints(
353353
await this.AssertStateChange(PowerShellContextState.Ready);
354354

355355
Task executeTask =
356-
this.powerShellContext.ExecuteScriptAtPath(
356+
this.powerShellContext.ExecuteScriptWithArgs(
357357
this.debugScriptFile.FilePath);
358358

359359
// Wait for conditional breakpoint to hit
@@ -389,7 +389,7 @@ await this.debugService.SetLineBreakpoints(
389389
await this.AssertStateChange(PowerShellContextState.Ready);
390390

391391
Task executeTask =
392-
this.powerShellContext.ExecuteScriptAtPath(
392+
this.powerShellContext.ExecuteScriptWithArgs(
393393
this.debugScriptFile.FilePath);
394394

395395
// Wait for conditional breakpoint to hit
@@ -466,7 +466,7 @@ public async Task DebuggerBreaksWhenRequested()
466466
this.debugService.Break();
467467

468468
// File path is an empty string when paused while running
469-
await this.AssertDebuggerStopped(string.Empty);
469+
await this.AssertDebuggerStopped(string.Empty);
470470
await this.AssertStateChange(
471471
PowerShellContextState.Ready,
472472
PowerShellExecutionResult.Stopped);
@@ -545,7 +545,7 @@ await this.debugService.SetLineBreakpoints(
545545

546546
StackFrameDetails[] stackFrames = debugService.GetStackFrames();
547547

548-
VariableDetailsBase[] variables =
548+
VariableDetailsBase[] variables =
549549
debugService.GetVariables(stackFrames[0].LocalVariables.Id);
550550

551551
// TODO: Add checks for correct value strings as well
@@ -604,7 +604,7 @@ await this.debugService.SetLineBreakpoints(
604604
Assert.Equal(newStrValue, setStrValue);
605605

606606
VariableScope[] scopes = this.debugService.GetVariableScopes(0);
607-
607+
608608
// Test set of script scope int variable (not strongly typed)
609609
VariableScope scriptScope = scopes.FirstOrDefault(s => s.Name == VariableContainerDetails.ScriptScopeName);
610610
string newIntValue = "49";

test/PowerShellEditorServices.Test/Session/PowerShellContextTests.cs

+2-2
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ public class PowerShellContextTests : IDisposable
3434

3535
private readonly ProfilePaths TestProfilePaths =
3636
new ProfilePaths(
37-
TestHostDetails.ProfileId,
37+
TestHostDetails.ProfileId,
3838
Path.GetFullPath(
3939
@"..\..\..\..\PowerShellEditorServices.Test.Shared\Profile"),
4040
Path.GetFullPath(
@@ -104,7 +104,7 @@ public async Task CanAbortExecution()
104104
Task.Run(
105105
async () =>
106106
{
107-
var unusedTask = this.powerShellContext.ExecuteScriptAtPath(DebugTestFilePath);
107+
var unusedTask = this.powerShellContext.ExecuteScriptWithArgs(DebugTestFilePath);
108108
await Task.Delay(50);
109109
this.powerShellContext.AbortExecution();
110110
});

0 commit comments

Comments
 (0)