@@ -43,6 +43,10 @@ public SynchronousPowerShellTask(
4343
4444 public override ExecutionOptions ExecutionOptions => PowerShellExecutionOptions ;
4545
46+ // These are PowerShell's intrinsic debugger commands that must be run via
47+ // `ProcessDebugCommand`.
48+ private static readonly string [ ] DebuggerCommands = { "continue" , "c" , "k" , "h" , "?" , "list" , "l" , "stepInto" , "s" , "stepOut" , "o" , "stepOver" , "v" , "quit" , "q" , "detach" , "d" } ;
49+
4650 public override IReadOnlyList < TResult > Run ( CancellationToken cancellationToken )
4751 {
4852 _pwsh = _psesHost . CurrentPowerShell ;
@@ -53,6 +57,7 @@ public override IReadOnlyList<TResult> Run(CancellationToken cancellationToken)
5357 }
5458
5559 return _pwsh . Runspace . Debugger . InBreakpoint
60+ && Array . Exists ( DebuggerCommands , c => c == _psCommand . GetInvocationText ( ) )
5661 ? ExecuteInDebugger ( cancellationToken )
5762 : ExecuteNormally ( cancellationToken ) ;
5863 }
@@ -87,9 +92,15 @@ private IReadOnlyList<TResult> ExecuteNormally(CancellationToken cancellationTok
8792 result = _pwsh . InvokeCommand < TResult > ( _psCommand , invocationSettings ) ;
8893 cancellationToken . ThrowIfCancellationRequested ( ) ;
8994 }
90- // Test if we've been cancelled. If we're remoting, PSRemotingDataStructureException effectively means the pipeline was stopped.
95+ // Test if we've been cancelled. If we're remoting, PSRemotingDataStructureException
96+ // effectively means the pipeline was stopped.
9197 catch ( Exception e ) when ( cancellationToken . IsCancellationRequested || e is PipelineStoppedException || e is PSRemotingDataStructureException )
9298 {
99+ // ExecuteNormally handles user commands in a debug session. Perhaps we should clean all this up somehow.
100+ if ( _pwsh . Runspace . Debugger . InBreakpoint )
101+ {
102+ StopDebuggerIfRemoteDebugSessionFailed ( ) ;
103+ }
93104 throw new OperationCanceledException ( ) ;
94105 }
95106 // We only catch RuntimeExceptions here in case writing errors to output was requested
@@ -122,6 +133,8 @@ private IReadOnlyList<TResult> ExecuteNormally(CancellationToken cancellationTok
122133
123134 private IReadOnlyList < TResult > ExecuteInDebugger ( CancellationToken cancellationToken )
124135 {
136+ // TODO: How much of this method can we remove now that it only processes PowerShell's
137+ // intrinsic debugger commands?
125138 cancellationToken . Register ( CancelDebugExecution ) ;
126139
127140 var outputCollection = new PSDataCollection < PSObject > ( ) ;
@@ -146,14 +159,22 @@ private IReadOnlyList<TResult> ExecuteInDebugger(CancellationToken cancellationT
146159 DebuggerCommandResults debuggerResult = null ;
147160 try
148161 {
149- // In the PowerShell debugger, extra debugger commands are made available, like "l", "s", "c", etc.
150- // Executing those commands produces a result that needs to be set on the debugger stop event args.
151- // So we use the Debugger.ProcessCommand() API to properly execute commands in the debugger
152- // and then call DebugContext.ProcessDebuggerResult() later to handle the command appropriately
162+ // In the PowerShell debugger, intrinsic debugger commands are made available, like
163+ // "l", "s", "c", etc. Executing those commands produces a result that needs to be
164+ // set on the debugger stop event args. So we use the Debugger.ProcessCommand() API
165+ // to properly execute commands in the debugger and then call
166+ // DebugContext.ProcessDebuggerResult() later to handle the command appropriately
167+ //
168+ // Unfortunately, this API does not allow us to pass in the InvocationSettings,
169+ // which means (for instance) that we cannot instruct it to avoid adding our
170+ // debugger implmentation's commands to the history. So instead we now only call
171+ // `ExecuteInDebugger` for PowerShell's own intrinsic debugger commands.
153172 debuggerResult = _pwsh . Runspace . Debugger . ProcessCommand ( _psCommand , outputCollection ) ;
154173 cancellationToken . ThrowIfCancellationRequested ( ) ;
155174 }
156- // Test if we've been cancelled. If we're remoting, PSRemotingDataStructureException effectively means the pipeline was stopped.
175+
176+ // Test if we've been cancelled. If we're remoting, PSRemotingDataStructureException
177+ // effectively means the pipeline was stopped.
157178 catch ( Exception e ) when ( cancellationToken . IsCancellationRequested || e is PipelineStoppedException || e is PSRemotingDataStructureException )
158179 {
159180 StopDebuggerIfRemoteDebugSessionFailed ( ) ;
0 commit comments