Skip to content

Commit 731759e

Browse files
adamdriscollTylerLeonhardt
authored andcommitted
Add attach to local runspace. (PowerShell#875)
* Add attach to local runspace. * Remove comment. * Use single runspaceId property. * Remove unnecessary processId check. * Factored if. * Update src/PowerShellEditorServices.Protocol/Server/DebugAdapter.cs It's neat that we can just commit a suggestion. Co-Authored-By: adamdriscoll <[email protected]> * Use runspace rather than dynamic. * Accept process ID for GetRunspaceRequest. * Clean up.
1 parent 1a7441c commit 731759e

File tree

4 files changed

+92
-3
lines changed

4 files changed

+92
-3
lines changed

src/PowerShellEditorServices.Protocol/DebugAdapter/AttachRequest.cs

+1-1
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ public class AttachRequestArguments
2020

2121
public string ProcessId { get; set; }
2222

23-
public int RunspaceId { get; set; }
23+
public string RunspaceId { get; set; }
2424

2525
public string CustomPipeName { get; set; }
2626
}
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<string, GetRunspaceResponse[], object, object> Type =
14+
RequestType<string, 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

+15-2
Original file line numberDiff line numberDiff line change
@@ -444,7 +444,7 @@ await requestContext.SendError(
444444
return;
445445
}
446446
}
447-
else
447+
else if (attachParams.ProcessId != "current")
448448
{
449449
Logger.Write(
450450
LogLevel.Error,
@@ -463,7 +463,20 @@ await requestContext.SendError(
463463
// will block the debug adapter initialization process. The
464464
// InitializedEvent will be sent as soon as the RunspaceChanged
465465
// event gets fired with the attached runspace.
466-
int runspaceId = attachParams.RunspaceId > 0 ? attachParams.RunspaceId : 1;
466+
467+
var runspaceId = 1;
468+
if (!int.TryParse(attachParams.RunspaceId, out runspaceId) || runspaceId <= 0)
469+
{
470+
Logger.Write(
471+
LogLevel.Error,
472+
$"Attach request failed, '{attachParams.RunspaceId}' is an invalid value for the processId.");
473+
474+
await requestContext.SendErrorAsync(
475+
"A positive integer must be specified for the RunspaceId field.");
476+
477+
return;
478+
}
479+
467480
_waitingForAttach = true;
468481
Task nonAwaitedTask = _editorSession.PowerShellContext
469482
.ExecuteScriptString($"\nDebug-Runspace -Id {runspaceId}")

src/PowerShellEditorServices.Protocol/Server/LanguageServer.cs

+51
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;
@@ -162,6 +163,8 @@ public void Start()
162163
this.messageHandlers.SetRequestHandler(GetPSHostProcessesRequest.Type, this.HandleGetPSHostProcessesRequest);
163164
this.messageHandlers.SetRequestHandler(CommentHelpRequest.Type, this.HandleCommentHelpRequest);
164165

166+
this.messageHandlers.SetRequestHandler(GetRunspaceRequest.Type, this.HandleGetRunspaceRequestAsync);
167+
165168
// Initialize the extension service
166169
// TODO: This should be made awaited once Initialize is async!
167170
this.editorSession.ExtensionService.Initialize(
@@ -1231,6 +1234,54 @@ protected async Task HandleCommentHelpRequest(
12311234
await requestContext.SendResult(result);
12321235
}
12331236

1237+
protected async Task HandleGetRunspaceRequestAsync(
1238+
string processId,
1239+
RequestContext<GetRunspaceResponse[]> requestContext)
1240+
{
1241+
var runspaceResponses = new List<GetRunspaceResponse>();
1242+
1243+
if (this.editorSession.PowerShellContext.LocalPowerShellVersion.Version.Major >= 5)
1244+
{
1245+
if (processId == null) {
1246+
processId = "current";
1247+
}
1248+
1249+
var isNotCurrentProcess = processId != null && processId != "current";
1250+
1251+
var psCommand = new PSCommand();
1252+
1253+
if (isNotCurrentProcess) {
1254+
psCommand.AddCommand("Enter-PSHostProcess").AddParameter("Id", processId).AddStatement();
1255+
}
1256+
1257+
psCommand.AddCommand("Get-Runspace");
1258+
1259+
StringBuilder sb = new StringBuilder();
1260+
IEnumerable<Runspace> runspaces = await editorSession.PowerShellContext.ExecuteCommandAsync<Runspace>(psCommand, sb);
1261+
if (runspaces != null)
1262+
{
1263+
foreach (var p in runspaces)
1264+
{
1265+
runspaceResponses.Add(
1266+
new GetRunspaceResponse
1267+
{
1268+
Id = p.Id,
1269+
Name = p.Name,
1270+
Availability = p.RunspaceAvailability.ToString()
1271+
});
1272+
}
1273+
}
1274+
1275+
if (isNotCurrentProcess) {
1276+
var exitCommand = new PSCommand();
1277+
exitCommand.AddCommand("Exit-PSHostProcess");
1278+
await editorSession.PowerShellContext.ExecuteCommandAsync(exitCommand);
1279+
}
1280+
}
1281+
1282+
await requestContext.SendResultAsync(runspaceResponses.ToArray());
1283+
}
1284+
12341285
private bool IsQueryMatch(string query, string symbolName)
12351286
{
12361287
return symbolName.IndexOf(query, StringComparison.OrdinalIgnoreCase) >= 0;

0 commit comments

Comments
 (0)