Skip to content

Commit d1ca49a

Browse files
committed
Add attach to local runspace.
1 parent 5a6299e commit d1ca49a

File tree

4 files changed

+91
-8
lines changed

4 files changed

+91
-8
lines changed

src/PowerShellEditorServices.Protocol/DebugAdapter/AttachRequest.cs

+2
Original file line numberDiff line numberDiff line change
@@ -21,5 +21,7 @@ public class AttachRequestArguments
2121
public string ProcessId { get; set; }
2222

2323
public int RunspaceId { get; set; }
24+
25+
public string LocalRunspaceId { get; set; }
2426
}
2527
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
//
2+
// Copyright (c) Microsoft. All rights reserved.
3+
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
4+
//
5+
6+
using Microsoft.PowerShell.EditorServices.Protocol.MessageProtocol;
7+
8+
namespace Microsoft.PowerShell.EditorServices.Protocol.LanguageServer
9+
{
10+
public class GetRunspaceRequest
11+
{
12+
public static readonly
13+
RequestType<object, GetRunspaceResponse[], object, object> Type =
14+
RequestType<object, GetRunspaceResponse[], object, object>.Create("powerShell/getRunspace");
15+
}
16+
17+
public class GetRunspaceResponse
18+
{
19+
public int Id { get; set; }
20+
21+
public string Name { get; set; }
22+
23+
public string Availability { get; set; }
24+
}
25+
}

src/PowerShellEditorServices.Protocol/Server/DebugAdapter.cs

+31-8
Original file line numberDiff line numberDiff line change
@@ -403,7 +403,7 @@ await requestContext.SendErrorAsync(
403403
_isRemoteAttach = true;
404404
}
405405

406-
if (int.TryParse(attachParams.ProcessId, out int processId) && (processId > 0))
406+
if ((int.TryParse(attachParams.ProcessId, out int processId) && (processId > 0)) || attachParams.ProcessId == "current")
407407
{
408408
PowerShellVersionDetails runspaceVersion =
409409
_editorSession.PowerShellContext.CurrentRunspace.PowerShellVersion;
@@ -416,16 +416,18 @@ await requestContext.SendErrorAsync(
416416
return;
417417
}
418418

419-
await _editorSession.PowerShellContext.ExecuteScriptStringAsync(
419+
if (attachParams.ProcessId != "current") {
420+
await _editorSession.PowerShellContext.ExecuteScriptStringAsync(
420421
$"Enter-PSHostProcess -Id {processId}",
421422
errorMessages);
422423

423-
if (errorMessages.Length > 0)
424-
{
425-
await requestContext.SendErrorAsync(
426-
$"Could not attach to process '{processId}'");
424+
if (errorMessages.Length > 0)
425+
{
426+
await requestContext.SendErrorAsync(
427+
$"Could not attach to process '{processId}'");
427428

428-
return;
429+
return;
430+
}
429431
}
430432

431433
// Clear any existing breakpoints before proceeding
@@ -435,7 +437,28 @@ await requestContext.SendErrorAsync(
435437
// will block the debug adapter initialization process. The
436438
// InitializedEvent will be sent as soon as the RunspaceChanged
437439
// event gets fired with the attached runspace.
438-
int runspaceId = attachParams.RunspaceId > 0 ? attachParams.RunspaceId : 1;
440+
441+
int runspaceId = 1;
442+
if (string.IsNullOrEmpty(attachParams.LocalRunspaceId))
443+
{
444+
runspaceId = attachParams.RunspaceId > 0 ? attachParams.RunspaceId : 1;
445+
}
446+
else if (int.TryParse(attachParams.LocalRunspaceId, out int localRunspaceId))
447+
{
448+
runspaceId = localRunspaceId;
449+
}
450+
else
451+
{
452+
Logger.Write(
453+
LogLevel.Error,
454+
$"Attach request failed, '{attachParams.LocalRunspaceId}' is an invalid value for the processId.");
455+
456+
await requestContext.SendErrorAsync(
457+
"A positive integer must be specified for the LocalRunspaceId field.");
458+
459+
return;
460+
}
461+
439462
_waitingForAttach = true;
440463
Task nonAwaitedTask =
441464
_editorSession.PowerShellContext

src/PowerShellEditorServices.Protocol/Server/LanguageServer.cs

+33
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
using System.Linq;
1919
using System.Management.Automation;
2020
using System.Management.Automation.Language;
21+
using System.Management.Automation.Runspaces;
2122
using System.Text;
2223
using System.Text.RegularExpressions;
2324
using System.Threading;
@@ -161,6 +162,8 @@ public void Start()
161162
this.messageHandlers.SetRequestHandler(GetPSHostProcessesRequest.Type, this.HandleGetPSHostProcessesRequestAsync);
162163
this.messageHandlers.SetRequestHandler(CommentHelpRequest.Type, this.HandleCommentHelpRequestAsync);
163164

165+
this.messageHandlers.SetRequestHandler(GetRunspaceRequest.Type, this.HandleGetRunspaceRequestAsync);
166+
164167
// Initialize the extension service
165168
// TODO: This should be made awaited once Initialize is async!
166169
this.editorSession.ExtensionService.InitializeAsync(
@@ -1218,6 +1221,36 @@ protected async Task HandleCommentHelpRequestAsync(
12181221
await requestContext.SendResultAsync(result);
12191222
}
12201223

1224+
protected async Task HandleGetRunspaceRequestAsync(
1225+
object noParams,
1226+
RequestContext<GetRunspaceResponse[]> requestContext)
1227+
{
1228+
var runspaceResponses = new List<GetRunspaceResponse>();
1229+
1230+
if (this.editorSession.PowerShellContext.LocalPowerShellVersion.Version.Major >= 5)
1231+
{
1232+
var psCommand = new PSCommand();
1233+
psCommand.AddCommand("Get-Runspace");
1234+
1235+
var runspaces = await editorSession.PowerShellContext.ExecuteCommandAsync<PSObject>(psCommand);
1236+
if (runspaces != null)
1237+
{
1238+
foreach (dynamic p in runspaces) //.Select(m => m.BaseObject as Runspace))
1239+
{
1240+
runspaceResponses.Add(
1241+
new GetRunspaceResponse
1242+
{
1243+
Id = p.Id,
1244+
Name = p.Name,
1245+
Availability = p.RunspaceAvailability.ToString()
1246+
});
1247+
}
1248+
}
1249+
}
1250+
1251+
await requestContext.SendResultAsync(runspaceResponses.ToArray());
1252+
}
1253+
12211254
private bool IsQueryMatch(string query, string symbolName)
12221255
{
12231256
return symbolName.IndexOf(query, StringComparison.OrdinalIgnoreCase) >= 0;

0 commit comments

Comments
 (0)