Skip to content

Commit

Permalink
backport #881 in a different way (#884)
Browse files Browse the repository at this point in the history
* backport #881 in a different way

* simpler

* switch back to reflecting

* address feedback

* more feedback

* safe check
  • Loading branch information
TylerLeonhardt authored Mar 21, 2019
1 parent 900b1b8 commit a96b282
Showing 1 changed file with 51 additions and 27 deletions.
78 changes: 51 additions & 27 deletions src/PowerShellEditorServices.Protocol/Server/LanguageServer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,9 @@
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Management.Automation;
using System.Management.Automation.Language;
using System.Management.Automation.Runspaces;
using System.Reflection;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading;
Expand All @@ -28,6 +28,8 @@

namespace Microsoft.PowerShell.EditorServices.Protocol.Server
{
using System.Management.Automation;

public class LanguageServer
{
private static CancellationTokenSource s_existingRequestCancellation;
Expand All @@ -42,6 +44,15 @@ public class LanguageServer

private static readonly SymbolInformation[] s_emptySymbolResult = new SymbolInformation[0];

// Since the NamedPipeConnectionInfo type is only available in 5.1+
// we have to use Activator to support older version of PS.
// This code only lives in the v1.X of the extension.
// The 2.x version of the code can be found here:
// https://github.com/PowerShell/PowerShellEditorServices/pull/881
private static readonly ConstructorInfo s_namedPipeConnectionInfoCtor = typeof(PSObject).GetTypeInfo().Assembly
.GetType("System.Management.Automation.Runspaces.NamedPipeConnectionInfo")
?.GetConstructor(new [] { typeof(int) });

private ILogger Logger;
private bool profilesLoaded;
private bool consoleReplStarted;
Expand Down Expand Up @@ -1234,48 +1245,61 @@ protected async Task HandleCommentHelpRequest(
await requestContext.SendResult(result);
}

private static Runspace GetRemoteRunspace(int pid)
{
var namedPipeConnectionInfoInstance = s_namedPipeConnectionInfoCtor.Invoke(new object[] { pid });
return RunspaceFactory.CreateRunspace(namedPipeConnectionInfoInstance as RunspaceConnectionInfo);
}

protected async Task HandleGetRunspaceRequestAsync(
string processId,
RequestContext<GetRunspaceResponse[]> requestContext)
{
var runspaceResponses = new List<GetRunspaceResponse>();
IEnumerable<PSObject> runspaces = null;

if (this.editorSession.PowerShellContext.LocalPowerShellVersion.Version.Major >= 5)
{
if (processId == null) {
processId = "current";
}

var isNotCurrentProcess = processId != null && processId != "current";

var psCommand = new PSCommand();

if (isNotCurrentProcess) {
psCommand.AddCommand("Enter-PSHostProcess").AddParameter("Id", processId).AddStatement();
}

psCommand.AddCommand("Get-Runspace");

StringBuilder sb = new StringBuilder();
IEnumerable<Runspace> runspaces = await editorSession.PowerShellContext.ExecuteCommand<Runspace>(psCommand, sb);
if (runspaces != null)
// If the processId is a valid int, we need to run Get-Runspace within that process
// otherwise just use the current runspace.
if (int.TryParse(processId, out int pid))
{
foreach (var p in runspaces)

// Create a remote runspace that we will invoke Get-Runspace in.
using(Runspace rs = GetRemoteRunspace(pid))
using(var ps = PowerShell.Create())
{
runspaceResponses.Add(
new GetRunspaceResponse
{
Id = p.Id,
Name = p.Name,
Availability = p.RunspaceAvailability.ToString()
});
rs.Open();
ps.Runspace = rs;
// Returns deserialized Runspaces. For simpler code, we use PSObject and rely on dynamic later.
runspaces = ps.AddCommand("Microsoft.PowerShell.Utility\\Get-Runspace").Invoke<PSObject>();
}
}
else
{
var psCommand = new PSCommand().AddCommand("Microsoft.PowerShell.Utility\\Get-Runspace");
var sb = new StringBuilder();
// returns (not deserialized) Runspaces. For simpler code, we use PSObject and rely on dynamic later.
runspaces = await editorSession.PowerShellContext.ExecuteCommand<PSObject>(psCommand, sb);
}
}

if (isNotCurrentProcess) {
var exitCommand = new PSCommand();
exitCommand.AddCommand("Exit-PSHostProcess");
await editorSession.PowerShellContext.ExecuteCommand(exitCommand);
var runspaceResponses = new List<GetRunspaceResponse>();

if (runspaces != null)
{
foreach (dynamic runspace in runspaces)
{
runspaceResponses.Add(
new GetRunspaceResponse
{
Id = runspace.Id,
Name = runspace.Name,
Availability = runspace.RunspaceAvailability.ToString()
});
}
}

Expand Down

0 comments on commit a96b282

Please sign in to comment.