Beispiel #1
0
 protected Task HandleAttachRequest(
     AttachRequestArguments attachParams,
     RequestContext <object> requestContext)
 {
     // TODO: Implement this once we support attaching to processes
     throw new NotImplementedException();
 }
        protected async Task HandleAttachRequestAsync(
            AttachRequestArguments attachParams,
            RequestContext <object> requestContext)
        {
            _isAttachSession = true;

            RegisterEventHandlers();

            // If there are no host processes to attach to or the user cancels selection, we get a null for the process id.
            // This is not an error, just a request to stop the original "attach to" request.
            // Testing against "undefined" is a HACK because I don't know how to make "Cancel" on quick pick loading
            // to cancel on the VSCode side without sending an attachRequest with processId set to "undefined".
            if (string.IsNullOrEmpty(attachParams.ProcessId) || (attachParams.ProcessId == "undefined"))
            {
                Logger.Write(
                    LogLevel.Normal,
                    $"Attach request aborted, received {attachParams.ProcessId} for processId.");

                await requestContext.SendErrorAsync(
                    "User aborted attach to PowerShell host process.");

                return;
            }

            StringBuilder errorMessages = new StringBuilder();

            if (attachParams.ComputerName != null)
            {
                PowerShellVersionDetails runspaceVersion =
                    _editorSession.PowerShellContext.CurrentRunspace.PowerShellVersion;

                if (runspaceVersion.Version.Major < 4)
                {
                    await requestContext.SendErrorAsync(
                        $"Remote sessions are only available with PowerShell 4 and higher (current session is {runspaceVersion.Version}).");

                    return;
                }
                else if (_editorSession.PowerShellContext.CurrentRunspace.Location == RunspaceLocation.Remote)
                {
                    await requestContext.SendErrorAsync(
                        $"Cannot attach to a process in a remote session when already in a remote session.");

                    return;
                }

                await _editorSession.PowerShellContext.ExecuteScriptStringAsync(
                    $"Enter-PSSession -ComputerName \"{attachParams.ComputerName}\"",
                    errorMessages);

                if (errorMessages.Length > 0)
                {
                    await requestContext.SendErrorAsync(
                        $"Could not establish remote session to computer '{attachParams.ComputerName}'");

                    return;
                }

                _isRemoteAttach = true;
            }

            if (int.TryParse(attachParams.ProcessId, out int processId) && (processId > 0))
            {
                PowerShellVersionDetails runspaceVersion =
                    _editorSession.PowerShellContext.CurrentRunspace.PowerShellVersion;

                if (runspaceVersion.Version.Major < 5)
                {
                    await requestContext.SendErrorAsync(
                        $"Attaching to a process is only available with PowerShell 5 and higher (current session is {runspaceVersion.Version}).");

                    return;
                }

                await _editorSession.PowerShellContext.ExecuteScriptStringAsync(
                    $"Enter-PSHostProcess -Id {processId}",
                    errorMessages);

                if (errorMessages.Length > 0)
                {
                    await requestContext.SendErrorAsync(
                        $"Could not attach to process '{processId}'");

                    return;
                }

                // Clear any existing breakpoints before proceeding
                await ClearSessionBreakpointsAsync();

                // Execute the Debug-Runspace command but don't await it because it
                // will block the debug adapter initialization process.  The
                // InitializedEvent will be sent as soon as the RunspaceChanged
                // event gets fired with the attached runspace.
                int runspaceId = attachParams.RunspaceId > 0 ? attachParams.RunspaceId : 1;
                _waitingForAttach = true;
                Task nonAwaitedTask =
                    _editorSession.PowerShellContext
                    .ExecuteScriptStringAsync($"\nDebug-Runspace -Id {runspaceId}")
                    .ContinueWith(OnExecutionCompletedAsync);
            }
            else
            {
                Logger.Write(
                    LogLevel.Error,
                    $"Attach request failed, '{attachParams.ProcessId}' is an invalid value for the processId.");

                await requestContext.SendErrorAsync(
                    "A positive integer must be specified for the processId field.");

                return;
            }

            await requestContext.SendResultAsync(null);
        }