Skip to content

Support ConstrainedLanguage mode #1269

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

Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
using System.Management.Automation;
using System.Reflection;
using SMA = System.Management.Automation;
using System.Management.Automation.Runspaces;
using Microsoft.PowerShell.EditorServices.Hosting;
using System.Globalization;
using System.Collections;
Expand Down Expand Up @@ -358,6 +359,7 @@ private EditorServicesConfig CreateConfigObject()
AdditionalModules = AdditionalModules,
LanguageServiceTransport = GetLanguageServiceTransport(),
DebugServiceTransport = GetDebugServiceTransport(),
LanguageMode = Runspace.DefaultRunspace.SessionStateProxy.LanguageMode,
ProfilePaths = new ProfilePathConfig
{
AllUsersAllHosts = GetProfilePathFromProfileObject(profile, ProfileUserKind.AllUsers, ProfileHostKind.AllHosts),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
//

using System.Collections.Generic;
using System.Management.Automation;
using System.Management.Automation.Host;

namespace Microsoft.PowerShell.EditorServices.Hosting
Expand Down Expand Up @@ -111,6 +112,11 @@ public EditorServicesConfig(
/// </summary>
public ProfilePathConfig ProfilePaths { get; set; }

/// <summary>
/// The language mode of the original runspace that we will inherit from.
/// </summary>
public PSLanguageMode LanguageMode { get; internal set; }

public string StartupBanner { get; set; } = @"

=====> PowerShell Integrated Console <=====
Expand Down
17 changes: 1 addition & 16 deletions src/PowerShellEditorServices.Hosting/EditorServicesLoader.cs
Original file line number Diff line number Diff line change
Expand Up @@ -190,8 +190,6 @@ public Task LoadAndRunEditorServicesAsync()
// Make sure the .NET Framework version supports .NET Standard 2.0
CheckNetFxVersion();
#endif
// Ensure the language mode allows us to run
CheckLanguageMode();

// Add the bundled modules to the PSModulePath
UpdatePSModulePath();
Expand Down Expand Up @@ -250,19 +248,6 @@ private void CheckNetFxVersion()
}
#endif

/// <summary>
/// PSES currently does not work in Constrained Language Mode, because PSReadLine script invocations won't work in it.
/// Ideally we can find a better way so that PSES will work in CLM.
/// </summary>
private void CheckLanguageMode()
{
_logger.Log(PsesLogLevel.Diagnostic, "Checking that PSES is running in FullLanguage mode");
if (Runspace.DefaultRunspace.SessionStateProxy.LanguageMode != PSLanguageMode.FullLanguage)
{
throw new InvalidOperationException("Cannot start PowerShell Editor Services in Constrained Language Mode");
}
}

private void UpdatePSModulePath()
{
if (string.IsNullOrEmpty(_hostConfig.BundledModulePath))
Expand Down Expand Up @@ -332,7 +317,7 @@ private string GetPSOutputEncoding()
{
using (var pwsh = SMA.PowerShell.Create())
{
return pwsh.AddScript("$OutputEncoding.EncodingName").Invoke<string>()[0];
return pwsh.AddScript("$OutputEncoding.EncodingName", useLocalScope: true).Invoke<string>()[0];
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -238,6 +238,7 @@ private HostStartupInfo CreateHostStartupInfo()
_config.FeatureFlags,
_config.AdditionalModules,
_config.LogPath,
_config.LanguageMode,
(int)_config.LogLevel,
consoleReplEnabled: _config.ConsoleRepl != ConsoleReplKind.None,
usesLegacyReadLine: _config.ConsoleRepl == ConsoleReplKind.LegacyReadLine);
Expand Down
8 changes: 8 additions & 0 deletions src/PowerShellEditorServices/Hosting/HostStartupInfo.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

using System;
using System.Collections.Generic;
using System.Management.Automation;
using System.Management.Automation.Host;

namespace Microsoft.PowerShell.EditorServices.Hosting
Expand Down Expand Up @@ -89,6 +90,11 @@ public sealed class HostStartupInfo
/// </summary>
public string LogPath { get; }

/// <summary>
/// The language mode of the original runspace that we will inherit from.
/// </summary>
public PSLanguageMode LanguageMode { get; }

/// <summary>
/// The minimum log level of log events to be logged.
/// </summary>
Expand Down Expand Up @@ -130,6 +136,7 @@ public HostStartupInfo(
IReadOnlyList<string> featureFlags,
IReadOnlyList<string> additionalModules,
string logPath,
PSLanguageMode languageMode,
int logLevel,
bool consoleReplEnabled,
bool usesLegacyReadLine)
Expand All @@ -142,6 +149,7 @@ public HostStartupInfo(
FeatureFlags = featureFlags ?? Array.Empty<string>();
AdditionalModules = additionalModules ?? Array.Empty<string>();
LogPath = logPath;
LanguageMode = languageMode;
LogLevel = logLevel;
ConsoleReplEnabled = consoleReplEnabled;
UsesLegacyReadLine = usesLegacyReadLine;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -213,7 +213,7 @@ public static PowerShellContextService Create(
hostUserInterface,
logger);

Runspace initialRunspace = PowerShellContextService.CreateRunspace(psHost);
Runspace initialRunspace = PowerShellContextService.CreateRunspace(psHost, hostStartupInfo.LanguageMode);
powerShellContext.Initialize(hostStartupInfo.ProfilePaths, initialRunspace, true, hostUserInterface);

powerShellContext.ImportCommandsModuleAsync();
Expand Down Expand Up @@ -260,15 +260,15 @@ public static Runspace CreateRunspace(
var psHost = new EditorServicesPSHost(powerShellContext, hostDetails, hostUserInterface, logger);
powerShellContext.ConsoleWriter = hostUserInterface;
powerShellContext.ConsoleReader = hostUserInterface;
return CreateRunspace(psHost);
return CreateRunspace(psHost, hostDetails.LanguageMode);
}

/// <summary>
///
/// </summary>
/// <param name="psHost"></param>
/// <returns></returns>
public static Runspace CreateRunspace(PSHost psHost)
public static Runspace CreateRunspace(PSHost psHost, PSLanguageMode languageMode)
{
InitialSessionState initialSessionState;
if (Environment.GetEnvironmentVariable("PSES_TEST_USE_CREATE_DEFAULT") == "1") {
Expand All @@ -277,6 +277,10 @@ public static Runspace CreateRunspace(PSHost psHost)
initialSessionState = InitialSessionState.CreateDefault2();
}

// Create and initialize a new Runspace while honoring the LanguageMode.
Console.WriteLine(languageMode);
initialSessionState.LanguageMode = languageMode;

Runspace runspace = RunspaceFactory.CreateRunspace(psHost, initialSessionState);

// Windows PowerShell must be hosted in STA mode
Expand Down Expand Up @@ -597,7 +601,7 @@ public async Task<IEnumerable<TResult>> ExecuteCommandAsync<TResult>(
// cancelled prompt when it's called again.
if (executionOptions.AddToHistory)
{
this.PromptContext.AddToHistory(psCommand.Commands[0].CommandText);
this.PromptContext.AddToHistory(executionOptions.InputString ?? psCommand.Commands[0].CommandText);
}

bool hadErrors = false;
Expand Down Expand Up @@ -686,7 +690,7 @@ public async Task<IEnumerable<TResult>> ExecuteCommandAsync<TResult>(
if (executionOptions.WriteInputToHost)
{
this.WriteOutput(
psCommand.Commands[0].CommandText,
executionOptions.InputString ?? psCommand.Commands[0].CommandText,
includeNewLine: true);
}

Expand Down Expand Up @@ -1161,7 +1165,7 @@ internal static TResult ExecuteScriptAndGetItem<TResult>(string scriptToExecute,
using (PowerShell pwsh = PowerShell.Create())
{
pwsh.Runspace = runspace;
IEnumerable<TResult> results = pwsh.AddScript(scriptToExecute).Invoke<TResult>();
IEnumerable<TResult> results = pwsh.AddScript(scriptToExecute, useLocalScope: true).Invoke<TResult>();
return results.DefaultIfEmpty(defaultValue).First();
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -121,14 +121,17 @@ public static DscBreakpointCapability CheckForCapability(
runspaceDetails.AddCapability(capability);

powerShell.Commands.Clear();
powerShell.AddScript("Write-Host \"Gathering DSC resource paths, this may take a while...\"");
powerShell.Invoke();
powerShell
.AddCommand("Microsoft.PowerShell.Utility\\Write-Host")
.AddArgument("Gathering DSC resource paths, this may take a while...")
.Invoke();

// Get the list of DSC resource paths
powerShell.Commands.Clear();
powerShell.AddCommand("Get-DscResource");
powerShell.AddCommand("Select-Object");
powerShell.AddParameter("ExpandProperty", "ParentPath");
powerShell
.AddCommand("Get-DscResource")
.AddCommand("Select-Object")
.AddParameter("ExpandProperty", "ParentPath");

Collection<PSObject> resourcePaths = null;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,18 @@ internal class ExecutionOptions
/// </summary>
public bool WriteInputToHost { get; set; }

/// <summary>
/// If this is set, we will use this string for history and writing to the host
/// instead of grabbing the command from the PSCommand.
/// </summary>
public string InputString { get; set; }

/// <summary>
/// If this is set, we will use this string for history and writing to the host
/// instead of grabbing the command from the PSCommand.
/// </summary>
public bool UseNewScope { get; set; }

/// <summary>
/// Gets or sets a value indicating whether the command to
/// be executed is a console input prompt, such as the
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ internal static bool TryGetPSReadLineProxy(
{
pwsh.Runspace = runspace;
var psReadLineType = pwsh
.AddScript(ReadLineInitScript)
.AddScript(ReadLineInitScript, useLocalScope: true)
.Invoke<Type>()
.FirstOrDefault();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,8 @@ public static PSCommand GetDetailsCommand()
{
PSCommand infoCommand = new PSCommand();
infoCommand.AddScript(
"@{ 'computerName' = if ([Environment]::MachineName) {[Environment]::MachineName} else {'localhost'}; 'processId' = $PID; 'instanceId' = $host.InstanceId }");
"@{ 'computerName' = if ([Environment]::MachineName) {[Environment]::MachineName} else {'localhost'}; 'processId' = $PID; 'instanceId' = $host.InstanceId }",
useLocalScope: true);

return infoCommand;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Management.Automation;
using System.Threading;
using System.Threading.Tasks;

Expand Down Expand Up @@ -46,6 +47,7 @@ public static PowerShellContextService Create(ILogger logger)
new List<string>(),
new List<string>(),
null,
PSLanguageMode.FullLanguage,
0,
consoleReplEnabled: false,
usesLegacyReadLine: false);
Expand Down