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); }