diff --git a/src/PowerShellEditorServices.Hosting/Commands/StartEditorServicesCommand.cs b/src/PowerShellEditorServices.Hosting/Commands/StartEditorServicesCommand.cs
index 0e698f812..acc52700a 100644
--- a/src/PowerShellEditorServices.Hosting/Commands/StartEditorServicesCommand.cs
+++ b/src/PowerShellEditorServices.Hosting/Commands/StartEditorServicesCommand.cs
@@ -349,6 +349,8 @@ private EditorServicesConfig CreateConfigObject()
var profile = (PSObject)GetVariableValue("profile");
var hostInfo = new HostInfo(HostName, HostProfileId, HostVersion);
+ var iss = Runspace.DefaultRunspace.InitialSessionState;
+ iss.LanguageMode = Runspace.DefaultRunspace.SessionStateProxy.LanguageMode;
var editorServicesConfig = new EditorServicesConfig(hostInfo, Host, SessionDetailsPath, bundledModulesPath, LogPath)
{
FeatureFlags = FeatureFlags,
@@ -357,7 +359,7 @@ private EditorServicesConfig CreateConfigObject()
AdditionalModules = AdditionalModules,
LanguageServiceTransport = GetLanguageServiceTransport(),
DebugServiceTransport = GetDebugServiceTransport(),
- LanguageMode = Runspace.DefaultRunspace.SessionStateProxy.LanguageMode,
+ InitialSessionState = iss,
ProfilePaths = new ProfilePathConfig
{
AllUsersAllHosts = GetProfilePathFromProfileObject(profile, ProfileUserKind.AllUsers, ProfileHostKind.AllHosts),
diff --git a/src/PowerShellEditorServices.Hosting/Configuration/EditorServicesConfig.cs b/src/PowerShellEditorServices.Hosting/Configuration/EditorServicesConfig.cs
index 5228ceced..79d49b83c 100644
--- a/src/PowerShellEditorServices.Hosting/Configuration/EditorServicesConfig.cs
+++ b/src/PowerShellEditorServices.Hosting/Configuration/EditorServicesConfig.cs
@@ -4,6 +4,7 @@
using System.Collections.Generic;
using System.Management.Automation;
using System.Management.Automation.Host;
+using System.Management.Automation.Runspaces;
namespace Microsoft.PowerShell.EditorServices.Hosting
{
@@ -111,10 +112,9 @@ public EditorServicesConfig(
public ProfilePathConfig ProfilePaths { get; set; }
///
- /// The language mode inherited from the orginal PowerShell process.
- /// This will be used when creating runspaces so that we honor the same language mode.
+ /// The InitialSessionState to use when creating runspaces. LanguageMode can be set here.
///
- public PSLanguageMode LanguageMode { get; internal set; }
+ public InitialSessionState InitialSessionState { get; internal set; }
public string StartupBanner { get; set; } = @"
diff --git a/src/PowerShellEditorServices.Hosting/Internal/EditorServicesRunner.cs b/src/PowerShellEditorServices.Hosting/Internal/EditorServicesRunner.cs
index e49da8527..a68842876 100644
--- a/src/PowerShellEditorServices.Hosting/Internal/EditorServicesRunner.cs
+++ b/src/PowerShellEditorServices.Hosting/Internal/EditorServicesRunner.cs
@@ -288,7 +288,7 @@ private HostStartupInfo CreateHostStartupInfo()
profilePaths,
_config.FeatureFlags,
_config.AdditionalModules,
- _config.LanguageMode,
+ _config.InitialSessionState,
_config.LogPath,
(int)_config.LogLevel,
consoleReplEnabled: _config.ConsoleRepl != ConsoleReplKind.None,
diff --git a/src/PowerShellEditorServices/Hosting/HostStartupInfo.cs b/src/PowerShellEditorServices/Hosting/HostStartupInfo.cs
index 9fc788e0d..be1491471 100644
--- a/src/PowerShellEditorServices/Hosting/HostStartupInfo.cs
+++ b/src/PowerShellEditorServices/Hosting/HostStartupInfo.cs
@@ -5,6 +5,7 @@
using System.Collections.Generic;
using System.Management.Automation;
using System.Management.Automation.Host;
+using System.Management.Automation.Runspaces;
namespace Microsoft.PowerShell.EditorServices.Hosting
{
@@ -92,10 +93,10 @@ public sealed class HostStartupInfo
public string LogPath { get; }
///
- /// The language mode inherited from the orginal PowerShell process.
- /// This will be used when creating runspaces so that we honor the same language mode.
+ /// The initialSessionState will be inherited from the orginal PowerShell process.
+ /// This will be used when creating runspaces so that we honor the same initialSessionState including allowed modules, cmdlets and language mode.
///
- public PSLanguageMode LanguageMode { get; }
+ public InitialSessionState InitialSessionState { get; }
///
/// The minimum log level of log events to be logged.
@@ -135,7 +136,7 @@ public sealed class HostStartupInfo
/// The path to the user specific profile.
/// Flags of features to enable.
/// Names or paths of additional modules to import.
- /// The language mode inherited from the orginal PowerShell process. This will be used when creating runspaces so that we honor the same language mode.
+ /// The language mode inherited from the orginal PowerShell process. This will be used when creating runspaces so that we honor the same initialSessionState including allowed modules, cmdlets and language mode.
/// The path to log to.
/// The minimum log event level.
/// Enable console if true.
@@ -149,7 +150,7 @@ public HostStartupInfo(
ProfilePathInfo profilePaths,
IReadOnlyList featureFlags,
IReadOnlyList additionalModules,
- PSLanguageMode languageMode,
+ InitialSessionState initialSessionState,
string logPath,
int logLevel,
bool consoleReplEnabled,
@@ -163,7 +164,7 @@ public HostStartupInfo(
ProfilePaths = profilePaths;
FeatureFlags = featureFlags ?? Array.Empty();
AdditionalModules = additionalModules ?? Array.Empty();
- LanguageMode = languageMode;
+ InitialSessionState = initialSessionState;
LogPath = logPath;
LogLevel = logLevel;
ConsoleReplEnabled = consoleReplEnabled;
diff --git a/src/PowerShellEditorServices/Services/PowerShellContext/PowerShellContextService.cs b/src/PowerShellEditorServices/Services/PowerShellContext/PowerShellContextService.cs
index 198cd26d9..f04e9c8ea 100644
--- a/src/PowerShellEditorServices/Services/PowerShellContext/PowerShellContextService.cs
+++ b/src/PowerShellEditorServices/Services/PowerShellContext/PowerShellContextService.cs
@@ -58,7 +58,7 @@ static PowerShellContextService()
{
MethodInfo setterInfo = typeof(Runspace).GetProperty("ApartmentState").GetSetMethod();
Delegate setter = Delegate.CreateDelegate(typeof(Action), firstArgument: null, method: setterInfo);
- s_runspaceApartmentStateSetter = (Action)setter;
+ s_runspaceApartmentStateSetter = (Action) setter;
}
if (VersionUtils.IsPS7OrGreater)
@@ -230,7 +230,7 @@ public static PowerShellContextService Create(
logger);
logger.LogTrace("Creating initial PowerShell runspace");
- Runspace initialRunspace = PowerShellContextService.CreateRunspace(psHost, hostStartupInfo.LanguageMode);
+ Runspace initialRunspace = PowerShellContextService.CreateRunspace(psHost, hostStartupInfo.InitialSessionState);
powerShellContext.Initialize(hostStartupInfo.ProfilePaths, initialRunspace, true, hostUserInterface);
powerShellContext.ImportCommandsModuleAsync();
@@ -251,7 +251,7 @@ public static PowerShellContextService Create(
sendErrorToHost: true);
#pragma warning restore CS4014
}
-
+
return powerShellContext;
}
@@ -263,7 +263,7 @@ public static PowerShellContextService Create(
/// The EditorServicesPSHostUserInterface to use for this instance.
/// An ILogger implementation to use for this instance.
///
- public static Runspace CreateRunspace(
+ public static Runspace CreateTestRunspace(
HostStartupInfo hostDetails,
PowerShellContextService powerShellContext,
EditorServicesPSHostUserInterface hostUserInterface,
@@ -274,7 +274,7 @@ public static Runspace CreateRunspace(
var psHost = new EditorServicesPSHost(powerShellContext, hostDetails, hostUserInterface, logger);
powerShellContext.ConsoleWriter = hostUserInterface;
powerShellContext.ConsoleReader = hostUserInterface;
- return CreateRunspace(psHost, hostDetails.LanguageMode);
+ return CreateRunspace(psHost, hostDetails.InitialSessionState);
}
///
@@ -283,29 +283,8 @@ public static Runspace CreateRunspace(
/// The PSHost that will be used for this Runspace.
/// The language mode inherited from the orginal PowerShell process. This will be used when creating runspaces so that we honor the same language mode.
///
- public static Runspace CreateRunspace(PSHost psHost, PSLanguageMode languageMode)
+ public static Runspace CreateRunspace(PSHost psHost, InitialSessionState initialSessionState)
{
- InitialSessionState initialSessionState;
- if (Environment.GetEnvironmentVariable("PSES_TEST_USE_CREATE_DEFAULT") == "1") {
- initialSessionState = InitialSessionState.CreateDefault();
- } else {
- initialSessionState = InitialSessionState.CreateDefault2();
- }
-
- // Create and initialize a new Runspace while honoring the LanguageMode of the original runspace
- // that started PowerShell Editor Services. This is because the PowerShell Integrated Console
- // should have the same LanguageMode of whatever is set by the system.
- initialSessionState.LanguageMode = languageMode;
-
- // We set the process scope's execution policy (which is really the runspace's scope) to
- // Bypass so we can import our bundled modules. This is equivalent in scope to the CLI
- // argument `-Bypass`, which (for instance) the extension passes. Thus we emulate this
- // behavior for consistency such that unit tests can pass in a similar environment.
- if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
- {
- initialSessionState.ExecutionPolicy = ExecutionPolicy.Bypass;
- }
-
Runspace runspace = RunspaceFactory.CreateRunspace(psHost, initialSessionState);
// Windows PowerShell must be hosted in STA mode
@@ -433,11 +412,6 @@ public void Initialize(
{
this.PromptContext = new LegacyReadLineContext(this);
}
-
- if (VersionUtils.IsWindows)
- {
- this.SetExecutionPolicy();
- }
}
///
@@ -1014,7 +988,7 @@ public Task> ExecuteScriptStringAsync(
Validate.IsNotNull(nameof(scriptString), scriptString);
PSCommand command = null;
- if(CurrentRunspace.Runspace.SessionStateProxy.LanguageMode != PSLanguageMode.FullLanguage)
+ if (CurrentRunspace.Runspace.SessionStateProxy.LanguageMode != PSLanguageMode.FullLanguage)
{
try
{
@@ -1029,7 +1003,7 @@ public Task> ExecuteScriptStringAsync(
}
// fall back to old behavior
- if(command == null)
+ if (command == null)
{
command = new PSCommand().AddScript(scriptString.Trim());
}
@@ -2152,7 +2126,7 @@ private static string GetStringForPSCommand(PSCommand psCommand)
return stringBuilder.ToString();
}
- private void SetExecutionPolicy()
+ internal void RestoreExecutionPolicy()
{
this.logger.LogTrace("Setting execution policy...");
@@ -2178,14 +2152,14 @@ private void SetExecutionPolicy()
// set to expected values, so we must sift through those.
ExecutionPolicy policyToSet = ExecutionPolicy.Bypass;
- var currentUserPolicy = (ExecutionPolicy)policies[policies.Count - 2].Members["ExecutionPolicy"].Value;
+ var currentUserPolicy = (ExecutionPolicy) policies[policies.Count - 2].Members["ExecutionPolicy"].Value;
if (currentUserPolicy != ExecutionPolicy.Undefined)
{
policyToSet = currentUserPolicy;
}
else
{
- var localMachinePolicy = (ExecutionPolicy)policies[policies.Count - 1].Members["ExecutionPolicy"].Value;
+ var localMachinePolicy = (ExecutionPolicy) policies[policies.Count - 1].Members["ExecutionPolicy"].Value;
if (localMachinePolicy != ExecutionPolicy.Undefined)
{
policyToSet = localMachinePolicy;
@@ -2357,7 +2331,7 @@ private void HandleRunspaceStateChanged(object sender, RunspaceStateEventArgs ar
case RunspaceState.Closed:
case RunspaceState.Broken:
// If the runspace closes or fails, pop the runspace
- ((IHostSupportsInteractiveSession)this).PopRunspace();
+ ((IHostSupportsInteractiveSession) this).PopRunspace();
break;
}
}
@@ -2369,7 +2343,7 @@ private static IEnumerable GetLoadableProfilePaths(ProfilePathInfo profi
yield break;
}
- foreach (string path in new [] { profilePaths.AllUsersAllHosts, profilePaths.AllUsersCurrentHost, profilePaths.CurrentUserAllHosts, profilePaths.CurrentUserCurrentHost })
+ foreach (string path in new[] { profilePaths.AllUsersAllHosts, profilePaths.AllUsersCurrentHost, profilePaths.CurrentUserAllHosts, profilePaths.CurrentUserCurrentHost })
{
if (path != null && File.Exists(path))
{
@@ -2401,12 +2375,12 @@ private void StartCommandLoopOnRunspaceAvailable()
void availabilityChangedHandler(object runspace, RunspaceAvailabilityEventArgs eventArgs)
{
if (eventArgs.RunspaceAvailability != RunspaceAvailability.Available ||
- this.versionSpecificOperations.IsDebuggerStopped(this.PromptNest, (Runspace)runspace))
+ this.versionSpecificOperations.IsDebuggerStopped(this.PromptNest, (Runspace) runspace))
{
return;
}
- ((Runspace)runspace).AvailabilityChanged -= availabilityChangedHandler;
+ ((Runspace) runspace).AvailabilityChanged -= availabilityChangedHandler;
Interlocked.Exchange(ref this.isCommandLoopRestarterSet, 0);
this.ConsoleReader?.StartCommandLoop();
}
diff --git a/test/PowerShellEditorServices.Test.E2E/PowerShellEditorServices.Test.E2E.csproj b/test/PowerShellEditorServices.Test.E2E/PowerShellEditorServices.Test.E2E.csproj
index 57a0514b6..c50895f2e 100644
--- a/test/PowerShellEditorServices.Test.E2E/PowerShellEditorServices.Test.E2E.csproj
+++ b/test/PowerShellEditorServices.Test.E2E/PowerShellEditorServices.Test.E2E.csproj
@@ -9,7 +9,7 @@
-
+
diff --git a/test/PowerShellEditorServices.Test/PowerShellContextFactory.cs b/test/PowerShellEditorServices.Test/PowerShellContextFactory.cs
index 41c3e4730..801d8f2f3 100644
--- a/test/PowerShellEditorServices.Test/PowerShellContextFactory.cs
+++ b/test/PowerShellEditorServices.Test/PowerShellContextFactory.cs
@@ -5,6 +5,8 @@
using System.Collections.Generic;
using System.IO;
using System.Management.Automation;
+using System.Management.Automation.Runspaces;
+using System.Runtime.InteropServices;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Extensions.Logging;
@@ -13,6 +15,7 @@
using Microsoft.PowerShell.EditorServices.Services;
using Microsoft.PowerShell.EditorServices.Services.PowerShellContext;
using Microsoft.PowerShell.EditorServices.Test.Shared;
+using Microsoft.PowerShell.EditorServices.Utility;
namespace Microsoft.PowerShell.EditorServices.Test
{
@@ -36,11 +39,19 @@ internal static class PowerShellContextFactory
TestUtilities.NormalizePath("../../../../../module"));
public static System.Management.Automation.Runspaces.Runspace InitialRunspace;
-
+
public static PowerShellContextService Create(ILogger logger)
{
PowerShellContextService powerShellContext = new PowerShellContextService(logger, null, isPSReadLineEnabled: false);
-
+ var initialSessionState = InitialSessionState.CreateDefault();
+ // We set the process scope's execution policy (which is really the runspace's scope) to
+ // Bypass so we can import our bundled modules. This is equivalent in scope to the CLI
+ // argument `-Bypass`, which (for instance) the extension passes. Thus we emulate this
+ // behavior for consistency such that unit tests can pass in a similar environment.
+ if(RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
+ {
+ initialSessionState.ExecutionPolicy = ExecutionPolicy.Bypass;
+ }
HostStartupInfo testHostDetails = new HostStartupInfo(
"PowerShell Editor Services Test Host",
"Test.PowerShellEditorServices",
@@ -49,27 +60,28 @@ public static PowerShellContextService Create(ILogger logger)
TestProfilePaths,
new List(),
new List(),
- // TODO: We want to replace this property with an entire initial session state,
- // which would then also control the process-scoped execution policy.
- PSLanguageMode.FullLanguage,
+ initialSessionState,
null,
0,
consoleReplEnabled: false,
usesLegacyReadLine: false,
bundledModulePath: BundledModulePath);
- InitialRunspace = PowerShellContextService.CreateRunspace(
+ InitialRunspace = PowerShellContextService.CreateTestRunspace(
testHostDetails,
powerShellContext,
new TestPSHostUserInterface(powerShellContext, logger),
logger);
-
+
powerShellContext.Initialize(
TestProfilePaths,
InitialRunspace,
ownsInitialRunspace: true,
consoleHost: null);
-
+ if(VersionUtils.IsWindows)
+ {
+ powerShellContext.RestoreExecutionPolicy();
+ }
return powerShellContext;
}
}