From f176687ba01f03702b967a746219084976dcdefd Mon Sep 17 00:00:00 2001 From: David Wilson Date: Tue, 21 Mar 2017 17:40:45 -0700 Subject: [PATCH 1/4] Show deprecation message in VS Code Debug Console This change causes a message to be displayed in VS Code's Debug Console if the user tries to execute a command there while debugging a PowerShell script. The message directs the user to open the Integrated Console instead. Resolves PowerShell/vscode-powershell#596. --- .../Server/DebugAdapter.cs | 58 +++++++++++++------ 1 file changed, 41 insertions(+), 17 deletions(-) diff --git a/src/PowerShellEditorServices.Protocol/Server/DebugAdapter.cs b/src/PowerShellEditorServices.Protocol/Server/DebugAdapter.cs index f75753645..3ce221565 100644 --- a/src/PowerShellEditorServices.Protocol/Server/DebugAdapter.cs +++ b/src/PowerShellEditorServices.Protocol/Server/DebugAdapter.cs @@ -295,6 +295,11 @@ await this.editorSession.PowerShellContext.ExecuteScriptString( "", false, true); } + if (this.editorSession.ConsoleService.EnableConsoleRepl) + { + await this.WriteUseIntegratedConsoleMessage(); + } + // Send the InitializedEvent so that the debugger will continue // sending configuration requests await this.SendEvent( @@ -743,23 +748,30 @@ protected async Task HandleEvaluateRequest( if (isFromRepl) { - // Check for special commands - if (string.Equals("!ctrlc", evaluateParams.Expression, StringComparison.CurrentCultureIgnoreCase)) - { - editorSession.PowerShellContext.AbortExecution(); - } - else if (string.Equals("!break", evaluateParams.Expression, StringComparison.CurrentCultureIgnoreCase)) + if (!this.editorSession.ConsoleService.EnableConsoleRepl) { - editorSession.DebugService.Break(); + // Check for special commands + if (string.Equals("!ctrlc", evaluateParams.Expression, StringComparison.CurrentCultureIgnoreCase)) + { + editorSession.PowerShellContext.AbortExecution(); + } + else if (string.Equals("!break", evaluateParams.Expression, StringComparison.CurrentCultureIgnoreCase)) + { + editorSession.DebugService.Break(); + } + else + { + // Send the input through the console service + var notAwaited = + this.editorSession + .PowerShellContext + .ExecuteScriptString(evaluateParams.Expression, false, true) + .ConfigureAwait(false); + } } else { - // Send the input through the console service - var notAwaited = - this.editorSession - .PowerShellContext - .ExecuteScriptString(evaluateParams.Expression, false, true) - .ConfigureAwait(false); + await this.WriteUseIntegratedConsoleMessage(); } } else @@ -770,10 +782,11 @@ protected async Task HandleEvaluateRequest( // has been resumed, return an empty result in this case. if (editorSession.PowerShellContext.IsDebuggerStopped) { - await editorSession.DebugService.EvaluateExpression( - evaluateParams.Expression, - evaluateParams.FrameId, - isFromRepl); + result = + await editorSession.DebugService.EvaluateExpression( + evaluateParams.Expression, + evaluateParams.FrameId, + isFromRepl); } if (result != null) @@ -793,6 +806,17 @@ await requestContext.SendResult( }); } + private async Task WriteUseIntegratedConsoleMessage() + { + await this.SendEvent( + OutputEvent.Type, + new OutputEventBody + { + Output = "\nThe Debug Console is no longer used for PowerShell debugging. Please use the 'PowerShell Integrated Console' to execute commands in the debugger. Run the 'PowerShell: Show Integrated Console' command to open it.", + Category = "stderr" + }); + } + #endregion #region Event Handlers From 8db08284e26ffb96c0f4b5177b81917c393cd956 Mon Sep 17 00:00:00 2001 From: David Wilson Date: Wed, 22 Mar 2017 10:44:13 -0700 Subject: [PATCH 2/4] Dot-source debugged scripts into the shared session This change causes scripts executed in the debugger to be dot-sourced into the shared session so that the functions defined in the script can be experimented with after debugging is complete. Resolves PowerShell/vscode-powershell#540. --- src/PowerShellEditorServices/Session/PowerShellContext.cs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/PowerShellEditorServices/Session/PowerShellContext.cs b/src/PowerShellEditorServices/Session/PowerShellContext.cs index c3e4c8966..c2f4286c1 100644 --- a/src/PowerShellEditorServices/Session/PowerShellContext.cs +++ b/src/PowerShellEditorServices/Session/PowerShellContext.cs @@ -699,15 +699,16 @@ public async Task ExecuteScriptWithArgs(string script, string arguments = null, // Related to issue #123. if (File.Exists(script) || File.Exists(scriptAbsPath)) { - script = EscapePath(script, escapeSpaces: true); + // Dot-source the launched script path + script = ". " + EscapePath(script, escapeSpaces: true); } launchedScript = script + " " + arguments; - command.AddScript(launchedScript); + command.AddScript(launchedScript, false); } else { - command.AddCommand(script); + command.AddCommand(script, false); } if (writeInputToHost) From 6390ce7193ed78a5563f8c41716b9a7a80690fb5 Mon Sep 17 00:00:00 2001 From: David Wilson Date: Wed, 22 Mar 2017 15:34:08 -0700 Subject: [PATCH 3/4] Support debugger commands in the Integrated Console. This change enables debugger commands in the integrated console by acting on the DebuggerResumeAction that is returned by the debugger when a command gets executed. If a DebuggerResumeAction is returned, it is used to resume the debugger in whatever way the user requested by typing a command. Resolves PowerShell/vscode-powershell#600. --- .../Server/DebugAdapter.cs | 13 ++++++++++++ .../Session/IVersionSpecificOperations.cs | 3 ++- .../Session/PowerShell3Operations.cs | 6 +++++- .../Session/PowerShell4Operations.cs | 8 +++++++- .../Session/PowerShellContext.cs | 20 ++++++++++++++----- 5 files changed, 42 insertions(+), 8 deletions(-) diff --git a/src/PowerShellEditorServices.Protocol/Server/DebugAdapter.cs b/src/PowerShellEditorServices.Protocol/Server/DebugAdapter.cs index 3ce221565..29142a83f 100644 --- a/src/PowerShellEditorServices.Protocol/Server/DebugAdapter.cs +++ b/src/PowerShellEditorServices.Protocol/Server/DebugAdapter.cs @@ -46,6 +46,7 @@ public DebugAdapter(EditorSession editorSession, ChannelBase serverChannel) this.editorSession = editorSession; this.editorSession.PowerShellContext.RunspaceChanged += this.powerShellContext_RunspaceChanged; this.editorSession.DebugService.DebuggerStopped += this.DebugService_DebuggerStopped; + this.editorSession.PowerShellContext.DebuggerResumed += this.powerShellContext_DebuggerResumed; } public DebugAdapter( @@ -60,6 +61,7 @@ public DebugAdapter( this.editorSession.StartDebugSession(hostDetails, profilePaths, editorOperations); this.editorSession.PowerShellContext.RunspaceChanged += this.powerShellContext_RunspaceChanged; this.editorSession.DebugService.DebuggerStopped += this.DebugService_DebuggerStopped; + this.editorSession.PowerShellContext.DebuggerResumed += this.powerShellContext_DebuggerResumed; // The assumption in this overload is that the debugger // is running in UI-hosted mode, no terminal interface @@ -891,6 +893,17 @@ await this.SendEvent( } } + private async void powerShellContext_DebuggerResumed(object sender, DebuggerResumeAction e) + { + await this.SendEvent( + ContinuedEvent.Type, + new ContinuedEvent + { + AllThreadsContinued = true, + ThreadId = 1 + }); + } + #endregion } } diff --git a/src/PowerShellEditorServices/Session/IVersionSpecificOperations.cs b/src/PowerShellEditorServices/Session/IVersionSpecificOperations.cs index f55ddbcab..d47264478 100644 --- a/src/PowerShellEditorServices/Session/IVersionSpecificOperations.cs +++ b/src/PowerShellEditorServices/Session/IVersionSpecificOperations.cs @@ -19,7 +19,8 @@ IEnumerable ExecuteCommandInDebugger( PowerShellContext powerShellContext, Runspace currentRunspace, PSCommand psCommand, - bool sendOutputToHost); + bool sendOutputToHost, + out DebuggerResumeAction? debuggerResumeAction); } } diff --git a/src/PowerShellEditorServices/Session/PowerShell3Operations.cs b/src/PowerShellEditorServices/Session/PowerShell3Operations.cs index 7b4ac4a9c..2199e1839 100644 --- a/src/PowerShellEditorServices/Session/PowerShell3Operations.cs +++ b/src/PowerShellEditorServices/Session/PowerShell3Operations.cs @@ -28,7 +28,8 @@ public IEnumerable ExecuteCommandInDebugger( PowerShellContext powerShellContext, Runspace currentRunspace, PSCommand psCommand, - bool sendOutputToHost) + bool sendOutputToHost, + out DebuggerResumeAction? debuggerResumeAction) { IEnumerable executionResult = null; @@ -63,6 +64,9 @@ public IEnumerable ExecuteCommandInDebugger( } } + // No DebuggerResumeAction result for PowerShell v3 + debuggerResumeAction = null; + return executionResult; } } diff --git a/src/PowerShellEditorServices/Session/PowerShell4Operations.cs b/src/PowerShellEditorServices/Session/PowerShell4Operations.cs index 4551ef996..ea4070225 100644 --- a/src/PowerShellEditorServices/Session/PowerShell4Operations.cs +++ b/src/PowerShellEditorServices/Session/PowerShell4Operations.cs @@ -33,8 +33,10 @@ public IEnumerable ExecuteCommandInDebugger( PowerShellContext powerShellContext, Runspace currentRunspace, PSCommand psCommand, - bool sendOutputToHost) + bool sendOutputToHost, + out DebuggerResumeAction? debuggerResumeAction) { + debuggerResumeAction = null; PSDataCollection outputCollection = new PSDataCollection(); #if !PowerShellv3 @@ -56,6 +58,10 @@ public IEnumerable ExecuteCommandInDebugger( currentRunspace.Debugger.ProcessCommand( psCommand, outputCollection); + + // Pass along the debugger's resume action if the user's + // command caused one to be returned + debuggerResumeAction = commandResults.ResumeAction; #endif IEnumerable results = null; diff --git a/src/PowerShellEditorServices/Session/PowerShellContext.cs b/src/PowerShellEditorServices/Session/PowerShellContext.cs index c2f4286c1..9ab7e839e 100644 --- a/src/PowerShellEditorServices/Session/PowerShellContext.cs +++ b/src/PowerShellEditorServices/Session/PowerShellContext.cs @@ -1089,11 +1089,21 @@ private IEnumerable ExecuteCommandInDebugger(PSCommand psComma "Attempting to execute command(s) in the debugger:\r\n\r\n{0}", GetStringForPSCommand(psCommand))); - return this.versionSpecificOperations.ExecuteCommandInDebugger( - this, - this.CurrentRunspace.Runspace, - psCommand, - sendOutputToHost); + IEnumerable output = + this.versionSpecificOperations.ExecuteCommandInDebugger( + this, + this.CurrentRunspace.Runspace, + psCommand, + sendOutputToHost, + out DebuggerResumeAction? debuggerResumeAction); + + if (debuggerResumeAction.HasValue) + { + // Resume the debugger with the specificed action + this.ResumeDebugger(debuggerResumeAction.Value); + } + + return output; } internal void WriteOutput(string outputString, bool includeNewLine) From 28617c647ae8e90622df33b7f67245906ef4ebbf Mon Sep 17 00:00:00 2001 From: David Wilson Date: Wed, 22 Mar 2017 15:36:38 -0700 Subject: [PATCH 4/4] Reset Console.TreatControlCAsInput when prompt is cancelled --- src/PowerShellEditorServices/Console/ConsoleService.cs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/PowerShellEditorServices/Console/ConsoleService.cs b/src/PowerShellEditorServices/Console/ConsoleService.cs index 3a14bd956..8cea74ee0 100644 --- a/src/PowerShellEditorServices/Console/ConsoleService.cs +++ b/src/PowerShellEditorServices/Console/ConsoleService.cs @@ -131,6 +131,10 @@ public void CancelReadLoop() { if (this.readLineCancellationToken != null) { + // Set this to false so that Ctrl+C isn't trapped by any + // lingering ReadKey + Console.TreatControlCAsInput = false; + this.readLineCancellationToken.Cancel(); this.readLineCancellationToken = null; }