diff --git a/module/PowerShellEditorServices/PowerShellEditorServices.psd1 b/module/PowerShellEditorServices/PowerShellEditorServices.psd1
index 4c5887f4f..77772c481 100644
--- a/module/PowerShellEditorServices/PowerShellEditorServices.psd1
+++ b/module/PowerShellEditorServices/PowerShellEditorServices.psd1
@@ -76,7 +76,11 @@ Copyright = '(c) 2017 Microsoft. All rights reserved.'
FunctionsToExport = @()
# Cmdlets to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no cmdlets to export.
-CmdletsToExport = @('Start-EditorServices')
+CmdletsToExport = @(
+ 'Start-EditorServices',
+ '__Invoke-ReadLineForEditorServices',
+ '__Invoke-ReadLineConstructor'
+)
# Variables to export from this module
VariablesToExport = @()
diff --git a/src/PowerShellEditorServices.Hosting/Commands/InvokeReadLineConstructorCommand.cs b/src/PowerShellEditorServices.Hosting/Commands/InvokeReadLineConstructorCommand.cs
new file mode 100644
index 000000000..48d28d16d
--- /dev/null
+++ b/src/PowerShellEditorServices.Hosting/Commands/InvokeReadLineConstructorCommand.cs
@@ -0,0 +1,24 @@
+//
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+//
+
+using System;
+using System.Management.Automation;
+using System.Runtime.CompilerServices;
+
+namespace Microsoft.PowerShell.EditorServices.Commands
+{
+ ///
+ /// The Start-EditorServices command, the conventional entrypoint for PowerShell Editor Services.
+ ///
+ [Cmdlet("__Invoke", "ReadLineConstructor")]
+ public sealed class InvokeReadLineConstructorCommand : PSCmdlet
+ {
+ protected override void EndProcessing()
+ {
+ Type type = Type.GetType("Microsoft.PowerShell.PSConsoleReadLine, Microsoft.PowerShell.PSReadLine2");
+ RuntimeHelpers.RunClassConstructor(type.TypeHandle);
+ }
+ }
+}
diff --git a/src/PowerShellEditorServices.Hosting/Commands/InvokeReadLineForEditorServicesCommand.cs b/src/PowerShellEditorServices.Hosting/Commands/InvokeReadLineForEditorServicesCommand.cs
new file mode 100644
index 000000000..7590f769d
--- /dev/null
+++ b/src/PowerShellEditorServices.Hosting/Commands/InvokeReadLineForEditorServicesCommand.cs
@@ -0,0 +1,56 @@
+//
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+//
+
+using System;
+using System.Management.Automation;
+using System.Management.Automation.Runspaces;
+using System.Reflection;
+using System.Threading;
+
+namespace Microsoft.PowerShell.EditorServices.Commands
+{
+ ///
+ /// The Start-EditorServices command, the conventional entrypoint for PowerShell Editor Services.
+ ///
+ [Cmdlet("__Invoke", "ReadLineForEditorServices")]
+ public sealed class InvokeReadLineForEditorServicesCommand : PSCmdlet
+ {
+ private delegate string ReadLineInvoker(
+ Runspace runspace,
+ EngineIntrinsics engineIntrinsics,
+ CancellationToken cancellationToken);
+
+ private static Lazy s_readLine = new Lazy(() =>
+ {
+ Type type = Type.GetType("Microsoft.PowerShell.PSConsoleReadLine, Microsoft.PowerShell.PSReadLine2");
+ MethodInfo method = type?.GetMethod(
+ "ReadLine",
+ new[] { typeof(Runspace), typeof(EngineIntrinsics), typeof(CancellationToken) });
+
+ // TODO: Handle method being null here. This shouldn't ever happen.
+
+ return (ReadLineInvoker)method.CreateDelegate(typeof(ReadLineInvoker));
+ });
+
+ ///
+ /// The ID to give to the host's profile.
+ ///
+ [Parameter(Mandatory = true)]
+ [ValidateNotNullOrEmpty]
+ public CancellationToken CancellationToken { get; set; }
+
+ protected override void EndProcessing()
+ {
+ // This returns a string.
+ object result = s_readLine.Value(
+ Runspace.DefaultRunspace,
+ SessionState.PSVariable.Get("ExecutionContext").Value as EngineIntrinsics,
+ CancellationToken
+ );
+
+ WriteObject(result);
+ }
+ }
+}
diff --git a/src/PowerShellEditorServices/Server/PsesDebugServer.cs b/src/PowerShellEditorServices/Server/PsesDebugServer.cs
index ea570a0d3..73b20546b 100644
--- a/src/PowerShellEditorServices/Server/PsesDebugServer.cs
+++ b/src/PowerShellEditorServices/Server/PsesDebugServer.cs
@@ -5,6 +5,7 @@
using System;
using System.IO;
+using System.Management.Automation;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Extensions.DependencyInjection;
@@ -80,8 +81,9 @@ public async Task StartAsync()
if (_usePSReadLine && _useTempSession && Interlocked.Exchange(ref s_hasRunPsrlStaticCtor, 1) == 0)
{
// This must be run synchronously to ensure debugging works
+ var command = new PSCommand().AddCommand("__Invoke-ReadLineConstructor");
_powerShellContextService
- .ExecuteScriptStringAsync("[System.Runtime.CompilerServices.RuntimeHelpers]::RunClassConstructor([Microsoft.PowerShell.PSConsoleReadLine].TypeHandle)")
+ .ExecuteCommandAsync