diff --git a/PowerShellEditorServices.Common.props b/PowerShellEditorServices.Common.props
index 2ab30ebc7..cdb72f19d 100644
--- a/PowerShellEditorServices.Common.props
+++ b/PowerShellEditorServices.Common.props
@@ -11,6 +11,5 @@
git
https://github.com/PowerShell/PowerShellEditorServices
portable
- $(DefineConstants);$(ExtraDefineConstants)
diff --git a/PowerShellEditorServices.build.ps1 b/PowerShellEditorServices.build.ps1
index 8df6c5fc1..fbd126708 100644
--- a/PowerShellEditorServices.build.ps1
+++ b/PowerShellEditorServices.build.ps1
@@ -259,20 +259,20 @@ task TestServer TestServerWinPS,TestServerPS7,TestServerPS72
task TestServerWinPS -If (-not $script:IsNix) {
Set-Location .\test\PowerShellEditorServices.Test\
- exec { & $script:dotnetExe test -p:ExtraDefineConstants=TEST --logger trx -f $script:NetRuntime.Desktop (DotNetTestFilter) }
+ exec { & $script:dotnetExe test --logger trx -f $script:NetRuntime.Desktop (DotNetTestFilter) }
}
task TestServerPS7 -If (-not $script:IsRosetta) {
Set-Location .\test\PowerShellEditorServices.Test\
Invoke-WithCreateDefaultHook -NewModulePath $script:PSCoreModulePath {
- exec { & $script:dotnetExe test -p:ExtraDefineConstants=TEST --logger trx -f $script:NetRuntime.PS7 (DotNetTestFilter) }
+ exec { & $script:dotnetExe test --logger trx -f $script:NetRuntime.PS7 (DotNetTestFilter) }
}
}
task TestServerPS72 {
Set-Location .\test\PowerShellEditorServices.Test\
Invoke-WithCreateDefaultHook -NewModulePath $script:PSCoreModulePath {
- exec { & $script:dotnetExe test -p:ExtraDefineConstants=TEST --logger trx -f $script:NetRuntime.PS72 (DotNetTestFilter) }
+ exec { & $script:dotnetExe test --logger trx -f $script:NetRuntime.PS72 (DotNetTestFilter) }
}
}
@@ -281,13 +281,13 @@ task TestE2E {
$env:PWSH_EXE_NAME = if ($IsCoreCLR) { "pwsh" } else { "powershell" }
$NetRuntime = if ($IsRosetta) { $script:NetRuntime.PS72 } else { $script:NetRuntime.PS7 }
- exec { & $script:dotnetExe test -p:ExtraDefineConstants=TEST --logger trx -f $NetRuntime (DotNetTestFilter) }
+ exec { & $script:dotnetExe test --logger trx -f $NetRuntime (DotNetTestFilter) }
# Run E2E tests in ConstrainedLanguage mode.
if (!$script:IsNix) {
try {
[System.Environment]::SetEnvironmentVariable("__PSLockdownPolicy", "0x80000007", [System.EnvironmentVariableTarget]::Machine);
- exec { & $script:dotnetExe test -p:ExtraDefineConstants=TEST --logger trx -f $script:NetRuntime.PS7 (DotNetTestFilter) }
+ exec { & $script:dotnetExe test --logger trx -f $script:NetRuntime.PS7 (DotNetTestFilter) }
} finally {
[System.Environment]::SetEnvironmentVariable("__PSLockdownPolicy", $null, [System.EnvironmentVariableTarget]::Machine);
}
diff --git a/src/PowerShellEditorServices.Hosting/Internal/EditorServicesRunner.cs b/src/PowerShellEditorServices.Hosting/Internal/EditorServicesRunner.cs
index b4dbf7c63..e49da8527 100644
--- a/src/PowerShellEditorServices.Hosting/Internal/EditorServicesRunner.cs
+++ b/src/PowerShellEditorServices.Hosting/Internal/EditorServicesRunner.cs
@@ -292,7 +292,8 @@ private HostStartupInfo CreateHostStartupInfo()
_config.LogPath,
(int)_config.LogLevel,
consoleReplEnabled: _config.ConsoleRepl != ConsoleReplKind.None,
- usesLegacyReadLine: _config.ConsoleRepl == ConsoleReplKind.LegacyReadLine);
+ usesLegacyReadLine: _config.ConsoleRepl == ConsoleReplKind.LegacyReadLine,
+ bundledModulePath: _config.BundledModulePath);
}
private void WriteStartupBanner()
diff --git a/src/PowerShellEditorServices/Hosting/HostStartupInfo.cs b/src/PowerShellEditorServices/Hosting/HostStartupInfo.cs
index 5f3ae7647..7612cd5a0 100644
--- a/src/PowerShellEditorServices/Hosting/HostStartupInfo.cs
+++ b/src/PowerShellEditorServices/Hosting/HostStartupInfo.cs
@@ -106,7 +106,10 @@ public sealed class HostStartupInfo
/// cref="Serilog.Events.LogEventLevel"/>, hence it is an int.
///
public int LogLevel { get; }
-
+ ///
+ /// The path to find the Bundled Modules ///
+ ///
+ public string BundledModulePath { get; }
#endregion
#region Constructors
@@ -135,6 +138,7 @@ public sealed class HostStartupInfo
/// The minimum log event level.
/// Enable console if true.
/// Use PSReadLine if false, otherwise use the legacy readline implementation.
+ /// The path to the Modules folder, helps with loading the bundled PSReadLine and other included modules
public HostStartupInfo(
string name,
string profileId,
@@ -147,7 +151,9 @@ public HostStartupInfo(
string logPath,
int logLevel,
bool consoleReplEnabled,
- bool usesLegacyReadLine)
+ bool usesLegacyReadLine,
+ string bundledModulePath
+ )
{
Name = name ?? DefaultHostName;
ProfileId = profileId ?? DefaultHostProfileId;
@@ -161,6 +167,7 @@ public HostStartupInfo(
LogLevel = logLevel;
ConsoleReplEnabled = consoleReplEnabled;
UsesLegacyReadLine = usesLegacyReadLine;
+ BundledModulePath = bundledModulePath;
}
#endregion
diff --git a/src/PowerShellEditorServices/Services/PowerShellContext/PowerShellContextService.cs b/src/PowerShellEditorServices/Services/PowerShellContext/PowerShellContextService.cs
index f226dd8d3..b98754951 100644
--- a/src/PowerShellEditorServices/Services/PowerShellContext/PowerShellContextService.cs
+++ b/src/PowerShellEditorServices/Services/PowerShellContext/PowerShellContextService.cs
@@ -32,10 +32,18 @@ namespace Microsoft.PowerShell.EditorServices.Services
///
internal class PowerShellContextService : IHostSupportsInteractiveSession
{
- private static readonly string s_commandsModulePath = Path.GetFullPath(
+ private static string s_bundledModulesPath = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "..", "..");
+
+ private static string s_commandsModulePath => Path.GetFullPath(
+ Path.Combine(
+ s_bundledModulesPath,
+ "PowerShellEditorServices",
+ "Commands",
+ "PowerShellEditorServices.Commands.psd1"));
+ private static string _psReadLineModulePath => Path.GetFullPath(
Path.Combine(
- Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location),
- "../../Commands/PowerShellEditorServices.Commands.psd1"));
+ s_bundledModulesPath,
+ "PSReadLine"));
private static readonly Action s_runspaceApartmentStateSetter;
private static readonly PropertyInfo s_writeStreamProperty;
@@ -190,7 +198,10 @@ public static PowerShellContextService Create(
HostStartupInfo hostStartupInfo)
{
Validate.IsNotNull(nameof(hostStartupInfo), hostStartupInfo);
-
+ s_bundledModulesPath = !string.IsNullOrEmpty(hostStartupInfo.BundledModulePath) && Directory.Exists(hostStartupInfo.BundledModulePath)
+ ? hostStartupInfo.BundledModulePath
+ : s_bundledModulesPath;
+
var logger = factory.CreateLogger();
bool shouldUsePSReadLine = hostStartupInfo.ConsoleReplEnabled
@@ -215,12 +226,18 @@ public static PowerShellContextService Create(
logger.LogTrace("Creating initial PowerShell runspace");
Runspace initialRunspace = PowerShellContextService.CreateRunspace(psHost, hostStartupInfo.LanguageMode);
- powerShellContext.Initialize(hostStartupInfo.ProfilePaths, initialRunspace, true, hostUserInterface);
+ powerShellContext.Initialize(hostStartupInfo, initialRunspace, true, hostUserInterface);
powerShellContext.ImportCommandsModuleAsync();
// TODO: This can be moved to the point after the $psEditor object
// gets initialized when that is done earlier than LanguageServer.Initialize
- foreach (string module in hostStartupInfo.AdditionalModules)
+ var modulesToImport = new List();
+ if(hostStartupInfo.ConsoleReplEnabled)
+ {
+ modulesToImport.Add(_psReadLineModulePath);
+ }
+ modulesToImport.AddRange(hostStartupInfo.AdditionalModules);
+ foreach (string module in modulesToImport)
{
var command =
new PSCommand()
@@ -305,7 +322,7 @@ public static Runspace CreateRunspace(PSHost psHost, PSLanguageMode languageMode
/// If true, the PowerShellContext owns this runspace.
/// An IHostOutput implementation. Optional.
public void Initialize(
- ProfilePathInfo profilePaths,
+ HostStartupInfo hostStartupInfo,
Runspace initialRunspace,
bool ownsInitialRunspace,
IHostOutput consoleHost)
@@ -359,7 +376,7 @@ public void Initialize(
this.ConfigureRunspaceCapabilities(this.CurrentRunspace);
// Set the $profile variable in the runspace
- this.profilePaths = profilePaths;
+ this.profilePaths = hostStartupInfo.ProfilePaths;
if (profilePaths != null)
{
this.SetProfileVariableInCurrentRunspace(profilePaths);
@@ -394,9 +411,14 @@ public void Initialize(
this.versionSpecificOperations);
this.InvocationEventQueue = InvocationEventQueue.Create(this, this.PromptNest);
+ if (VersionUtils.IsWindows)
+ {
+ this.SetExecutionPolicy();
+ }
+
if (powerShellVersion.Major >= 5 &&
this.isPSReadLineEnabled &&
- PSReadLinePromptContext.TryGetPSReadLineProxy(logger, initialRunspace, out PSReadLineProxy proxy))
+ PSReadLinePromptContext.TryGetPSReadLineProxy(logger, initialRunspace, hostStartupInfo.BundledModulePath, out PSReadLineProxy proxy))
{
this.PromptContext = new PSReadLinePromptContext(
this,
@@ -409,10 +431,6 @@ public void Initialize(
this.PromptContext = new LegacyReadLineContext(this);
}
- if (VersionUtils.IsWindows)
- {
- this.SetExecutionPolicy();
- }
}
///
diff --git a/src/PowerShellEditorServices/Services/PowerShellContext/Session/PSReadLinePromptContext.cs b/src/PowerShellEditorServices/Services/PowerShellContext/Session/PSReadLinePromptContext.cs
index 5f4931854..3633ad1d3 100644
--- a/src/PowerShellEditorServices/Services/PowerShellContext/Session/PSReadLinePromptContext.cs
+++ b/src/PowerShellEditorServices/Services/PowerShellContext/Session/PSReadLinePromptContext.cs
@@ -17,20 +17,6 @@ namespace Microsoft.PowerShell.EditorServices.Services.PowerShellContext
internal class PSReadLinePromptContext : IPromptContext
{
- private static readonly string _psReadLineModulePath = Path.Combine(
- Path.GetDirectoryName(typeof(PSReadLinePromptContext).Assembly.Location),
- "..",
- "..",
- "..",
-#if TEST
- // When using xUnit (dotnet test) the assemblies are deployed to the
- // test project folder, invalidating our relative path assumption.
- "..",
- "..",
- "module",
-#endif
- "PSReadLine");
-
private static readonly Lazy s_lazyInvokeReadLineForEditorServicesCmdletInfo = new Lazy(() =>
{
var type = Type.GetType("Microsoft.PowerShell.EditorServices.Commands.InvokeReadLineForEditorServicesCommand, Microsoft.PowerShell.EditorServices.Hosting");
@@ -79,9 +65,11 @@ internal PSReadLinePromptContext(
internal static bool TryGetPSReadLineProxy(
ILogger logger,
Runspace runspace,
+ string bundledModulePath,
out PSReadLineProxy readLineProxy)
{
readLineProxy = null;
+ string _psReadLineModulePath = Path.Combine(bundledModulePath, "PSReadLine");
logger.LogTrace("Attempting to load PSReadLine");
using (var pwsh = PowerShell.Create())
{
@@ -94,10 +82,24 @@ internal static bool TryGetPSReadLineProxy(
if (psReadLineType == null)
{
- logger.LogWarning("PSConsoleReadline type not found: {Reason}", pwsh.HadErrors ? pwsh.Streams.Error[0].ToString() : "");
- return false;
+ logger.LogWarning("PSConsoleReadline type not found using Type.GetType(): {Reason}", pwsh.HadErrors ? pwsh.Streams.Error[0].ToString() : "");
+ logger.LogWarning("Searching loaded assemblies...");
+ var allAssemblies = AppDomain.CurrentDomain.GetAssemblies();
+ var assemblies = allAssemblies.FirstOrDefault(a => a.FullName.Contains("Microsoft.PowerShell.PSReadLine2"));
+ var type = assemblies?.ExportedTypes?.FirstOrDefault(a => a.FullName == "Microsoft.PowerShell.PSConsoleReadLine");
+ if(type is not null)
+ {
+ logger.LogInformation("Found PSConsoleReadLine in loaded assemblies.");
+ psReadLineType = type;
+ }
+ else
+ {
+ logger.LogError("Unable to find PSConsoleReadLine in loaded assembles.");
+ return false;
+ }
}
+
try
{
readLineProxy = new PSReadLineProxy(psReadLineType, logger);
@@ -108,6 +110,7 @@ internal static bool TryGetPSReadLineProxy(
// Could be an older version, a custom build, or something a newer version with
// breaking changes.
logger.LogWarning("PSReadLineProxy unable to be initialized: {Reason}", e);
+ System.Console.WriteLine("PSReadLineProxy unable to be initialized");
return false;
}
}
diff --git a/test/PowerShellEditorServices.Test/PowerShellContextFactory.cs b/test/PowerShellEditorServices.Test/PowerShellContextFactory.cs
index 4eb93395a..5fd8ecbd1 100644
--- a/test/PowerShellEditorServices.Test/PowerShellContextFactory.cs
+++ b/test/PowerShellEditorServices.Test/PowerShellContextFactory.cs
@@ -31,6 +31,9 @@ internal static class PowerShellContextFactory
TestUtilities.NormalizePath("../../../../PowerShellEditorServices.Test.Shared/Test.PowerShellEditorServices_profile.ps1")),
Path.GetFullPath(
TestUtilities.NormalizePath("../../../../PowerShellEditorServices.Test.Shared/ProfileTest.ps1")));
+ public static readonly string BundledModulesPath =
+ Path.GetFullPath(
+ TestUtilities.NormalizePath("../../../../../module"));
public static System.Management.Automation.Runspaces.Runspace initialRunspace;
@@ -50,7 +53,8 @@ public static PowerShellContextService Create(ILogger logger)
null,
0,
consoleReplEnabled: false,
- usesLegacyReadLine: false);
+ usesLegacyReadLine: false,
+ bundledModulePath: BundledModulesPath);
initialRunspace = PowerShellContextService.CreateRunspace(
testHostDetails,
@@ -59,7 +63,7 @@ public static PowerShellContextService Create(ILogger logger)
logger);
powerShellContext.Initialize(
- TestProfilePaths,
+ testHostDetails,
initialRunspace,
ownsInitialRunspace: true,
consoleHost: null);
diff --git a/test/PowerShellEditorServices.Test/Session/PowerShellContextTests.cs b/test/PowerShellEditorServices.Test/Session/PowerShellContextTests.cs
index 4cf1fef8c..16043aaac 100644
--- a/test/PowerShellEditorServices.Test/Session/PowerShellContextTests.cs
+++ b/test/PowerShellEditorServices.Test/Session/PowerShellContextTests.cs
@@ -6,6 +6,7 @@
using System.IO;
using System.Linq;
using System.Management.Automation;
+using System.Reflection;
using System.Runtime.InteropServices;
using System.Threading.Tasks;
using Microsoft.Extensions.Logging.Abstractions;
@@ -151,11 +152,20 @@ await this.powerShellContext.ExecuteCommandAsync(
[SkippableFact]
public async Task CanGetPSReadLineProxy()
{
- Skip.If(IsWindows, "This test doesn't work on Windows for some reason.");
+ var directory = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, AppDomain.CurrentDomain.RelativeSearchPath ?? "");
+ string s_bundledModulesPath = Path.GetFullPath(Path.Combine(directory,
+ "..",
+ "..",
+ "..",
+ "..",
+ "..",
+ "module"
+ ));
Assert.True(PSReadLinePromptContext.TryGetPSReadLineProxy(
- NullLogger.Instance,
- PowerShellContextFactory.initialRunspace,
- out PSReadLineProxy proxy));
+ NullLogger.Instance,
+ PowerShellContextFactory.initialRunspace,
+ s_bundledModulesPath,
+ out PSReadLineProxy proxy));
}
#region Helper Methods