diff --git a/src/PowerShellEditorServices/Services/DebugAdapter/Handlers/LaunchAndAttachHandler.cs b/src/PowerShellEditorServices/Services/DebugAdapter/Handlers/LaunchAndAttachHandler.cs index c2ae8becb..8b5b4dee6 100644 --- a/src/PowerShellEditorServices/Services/DebugAdapter/Handlers/LaunchAndAttachHandler.cs +++ b/src/PowerShellEditorServices/Services/DebugAdapter/Handlers/LaunchAndAttachHandler.cs @@ -436,7 +436,7 @@ await _executionService.ExecutePSCommandAsync( _debugStateService.WaitingForAttach = true; Task nonAwaitedTask = _executionService .ExecutePSCommandAsync(debugRunspaceCmd, CancellationToken.None, PowerShellExecutionOptions.ImmediateInteractive) - .ContinueWith( OnExecutionCompletedAsync, TaskScheduler.Default); + .ContinueWith(OnExecutionCompletedAsync, TaskScheduler.Default); if (runspaceVersion.Version.Major >= 7) { diff --git a/src/PowerShellEditorServices/Services/Extension/ExtensionService.cs b/src/PowerShellEditorServices/Services/Extension/ExtensionService.cs index 028fe0f19..4405a4ce7 100644 --- a/src/PowerShellEditorServices/Services/Extension/ExtensionService.cs +++ b/src/PowerShellEditorServices/Services/Extension/ExtensionService.cs @@ -14,6 +14,37 @@ namespace Microsoft.PowerShell.EditorServices.Services.Extension { + /// Enumerates the possible execution results that can occur after + /// executing a command or script. + /// + internal enum ExecutionStatus + { + /// + /// Indicates that execution has not yet started. + /// + Pending, + + /// + /// Indicates that the command is executing. + /// + Running, + + /// + /// Indicates that execution has failed. + /// + Failed, + + /// + /// Indicates that execution was aborted by the user. + /// + Aborted, + + /// + /// Indicates that execution completed successfully. + /// + Completed + } + /// /// Provides a high-level service which enables PowerShell scripts /// and modules to extend the behavior of the host editor. @@ -123,6 +154,7 @@ internal Task InitializeAsync() /// The command being invoked was not registered. public Task InvokeCommandAsync(string commandName, EditorContext editorContext, CancellationToken cancellationToken) { + _languageServer?.SendNotification("powerShell/executionStatusChanged", ExecutionStatus.Pending); if (editorCommands.TryGetValue(commandName, out EditorCommand editorCommand)) { PSCommand executeCommand = new PSCommand() @@ -131,6 +163,7 @@ public Task InvokeCommandAsync(string commandName, EditorContext editorContext, .AddParameter("ArgumentList", new object[] { editorContext }); // This API is used for editor command execution so it requires the foreground. + _languageServer?.SendNotification("powerShell/executionStatusChanged", ExecutionStatus.Running); return ExecutionService.ExecutePSCommandAsync( executeCommand, cancellationToken, @@ -140,9 +173,27 @@ public Task InvokeCommandAsync(string commandName, EditorContext editorContext, WriteOutputToHost = !editorCommand.SuppressOutput, AddToHistory = !editorCommand.SuppressOutput, ThrowOnError = false, - }); + }).ContinueWith((Task executeTask) => + { + ExecutionStatus status = ExecutionStatus.Failed; + if (executeTask.IsCompleted) + { + status = ExecutionStatus.Completed; + } + else if (executeTask.IsCanceled) + { + status = ExecutionStatus.Aborted; + } + else if (executeTask.IsFaulted) + { + status = ExecutionStatus.Failed; + } + + _languageServer?.SendNotification("powerShell/executionStatusChanged", status); + }, TaskScheduler.Default); } + _languageServer?.SendNotification("powerShell/executionStatusChanged", ExecutionStatus.Failed); throw new KeyNotFoundException($"Editor command not found: '{commandName}'"); }