-
Notifications
You must be signed in to change notification settings - Fork 234
Add attach to local runspace. #875
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 2 commits
d1ca49a
c794be4
384b91a
75220a6
70a2e12
cbe5b18
28f3840
1d79002
6466c44
015c1ef
bb984a0
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
// | ||
// Copyright (c) Microsoft. All rights reserved. | ||
// Licensed under the MIT license. See LICENSE file in the project root for full license information. | ||
// | ||
|
||
using Microsoft.PowerShell.EditorServices.Protocol.MessageProtocol; | ||
|
||
namespace Microsoft.PowerShell.EditorServices.Protocol.LanguageServer | ||
{ | ||
public class GetRunspaceRequest | ||
{ | ||
public static readonly | ||
RequestType<object, GetRunspaceResponse[], object, object> Type = | ||
RequestType<object, GetRunspaceResponse[], object, object>.Create("powerShell/getRunspace"); | ||
} | ||
|
||
public class GetRunspaceResponse | ||
{ | ||
public int Id { get; set; } | ||
|
||
public string Name { get; set; } | ||
|
||
public string Availability { get; set; } | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -403,7 +403,7 @@ await requestContext.SendErrorAsync( | |
_isRemoteAttach = true; | ||
} | ||
|
||
if (int.TryParse(attachParams.ProcessId, out int processId) && (processId > 0)) | ||
if ((int.TryParse(attachParams.ProcessId, out int processId) && (processId > 0)) || attachParams.ProcessId == "current") | ||
{ | ||
PowerShellVersionDetails runspaceVersion = | ||
_editorSession.PowerShellContext.CurrentRunspace.PowerShellVersion; | ||
|
@@ -416,16 +416,18 @@ await requestContext.SendErrorAsync( | |
return; | ||
} | ||
|
||
await _editorSession.PowerShellContext.ExecuteScriptStringAsync( | ||
if (attachParams.ProcessId != "current") { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Shouldn't need this if because the outer if (processIdIsSet && int.TryParse(attachParams.ProcessId, out int processId) && (processId > 0)) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Good catch. Updated the PR. |
||
await _editorSession.PowerShellContext.ExecuteScriptStringAsync( | ||
$"Enter-PSHostProcess -Id {processId}", | ||
errorMessages); | ||
|
||
if (errorMessages.Length > 0) | ||
{ | ||
await requestContext.SendErrorAsync( | ||
$"Could not attach to process '{processId}'"); | ||
if (errorMessages.Length > 0) | ||
{ | ||
await requestContext.SendErrorAsync( | ||
$"Could not attach to process '{processId}'"); | ||
|
||
return; | ||
return; | ||
} | ||
} | ||
|
||
// Clear any existing breakpoints before proceeding | ||
|
@@ -435,7 +437,28 @@ await requestContext.SendErrorAsync( | |
// 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; | ||
|
||
int runspaceId = 1; | ||
if (string.IsNullOrEmpty(attachParams.LocalRunspaceId)) | ||
{ | ||
runspaceId = attachParams.RunspaceId > 0 ? attachParams.RunspaceId : 1; | ||
} | ||
else if (int.TryParse(attachParams.LocalRunspaceId, out int localRunspaceId)) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Seems like we could There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Sweet. Works for me. I will update these PRs sometime this weekend. |
||
{ | ||
runspaceId = localRunspaceId; | ||
} | ||
else | ||
{ | ||
Logger.Write( | ||
LogLevel.Error, | ||
$"Attach request failed, '{attachParams.LocalRunspaceId}' is an invalid value for the processId."); | ||
|
||
await requestContext.SendErrorAsync( | ||
"A positive integer must be specified for the LocalRunspaceId field."); | ||
|
||
return; | ||
} | ||
|
||
_waitingForAttach = true; | ||
Task nonAwaitedTask = | ||
_editorSession.PowerShellContext | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -18,6 +18,7 @@ | |
using System.Linq; | ||
using System.Management.Automation; | ||
using System.Management.Automation.Language; | ||
using System.Management.Automation.Runspaces; | ||
using System.Text; | ||
using System.Text.RegularExpressions; | ||
using System.Threading; | ||
|
@@ -161,6 +162,8 @@ public void Start() | |
this.messageHandlers.SetRequestHandler(GetPSHostProcessesRequest.Type, this.HandleGetPSHostProcessesRequestAsync); | ||
this.messageHandlers.SetRequestHandler(CommentHelpRequest.Type, this.HandleCommentHelpRequestAsync); | ||
|
||
this.messageHandlers.SetRequestHandler(GetRunspaceRequest.Type, this.HandleGetRunspaceRequestAsync); | ||
|
||
// Initialize the extension service | ||
// TODO: This should be made awaited once Initialize is async! | ||
this.editorSession.ExtensionService.InitializeAsync( | ||
|
@@ -1218,6 +1221,36 @@ protected async Task HandleCommentHelpRequestAsync( | |
await requestContext.SendResultAsync(result); | ||
} | ||
|
||
protected async Task HandleGetRunspaceRequestAsync( | ||
object noParams, | ||
RequestContext<GetRunspaceResponse[]> requestContext) | ||
{ | ||
var runspaceResponses = new List<GetRunspaceResponse>(); | ||
|
||
if (this.editorSession.PowerShellContext.LocalPowerShellVersion.Version.Major >= 5) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Was There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. That's a really good question. I just took that check from the process picker but I'm not sure when Debug-Runspace\Get-Runspace was added. I can try and find out. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Well looks like that answers our question :) |
||
{ | ||
var psCommand = new PSCommand(); | ||
psCommand.AddCommand("Get-Runspace"); | ||
|
||
var runspaces = await editorSession.PowerShellContext.ExecuteCommandAsync<PSObject>(psCommand); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. can you replace There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Also, instead of PSObject you should be able to do There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 👍 |
||
if (runspaces != null) | ||
{ | ||
foreach (dynamic p in runspaces) | ||
{ | ||
runspaceResponses.Add( | ||
new GetRunspaceResponse | ||
{ | ||
Id = p.Id, | ||
Name = p.Name, | ||
Availability = p.RunspaceAvailability.ToString() | ||
}); | ||
} | ||
} | ||
} | ||
|
||
await requestContext.SendResultAsync(runspaceResponses.ToArray()); | ||
} | ||
|
||
private bool IsQueryMatch(string query, string symbolName) | ||
{ | ||
return symbolName.IndexOf(query, StringComparison.OrdinalIgnoreCase) >= 0; | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just asking but ... do we really need two different fields for runspace id?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
BTW if it would be more convenient if
RunspaceId
was a string, we change the type I think. We'd just update the VSCode debug attach code to stringify the runspace id number.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
OK. I can make that change. That's pretty much the reason I added another field was that I didn't wanna mess with RunspaceId's type but I'm happy to adjust that to eliminate the new property.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I guess I was curious how this affects existing launch.json files. Is there something we need to do to ensure that they get upgraded in some way or will a number just work?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I just tried this. Seems to still work. It complains in the launch.json that the number should be a string but the attaching still works.