diff --git a/src/PowerShellEditorServices.Hosting/Commands/StartEditorServicesCommand.cs b/src/PowerShellEditorServices.Hosting/Commands/StartEditorServicesCommand.cs
index 4589b9a44..b2b75cfbc 100644
--- a/src/PowerShellEditorServices.Hosting/Commands/StartEditorServicesCommand.cs
+++ b/src/PowerShellEditorServices.Hosting/Commands/StartEditorServicesCommand.cs
@@ -351,6 +351,7 @@ private EditorServicesConfig CreateConfigObject()
FeatureFlags = FeatureFlags,
LogLevel = LogLevel,
ConsoleRepl = GetReplKind(),
+ UseNullPSHostUI = Stdio, // If Stdio is used we can't write anything else out
AdditionalModules = AdditionalModules,
LanguageServiceTransport = GetLanguageServiceTransport(),
DebugServiceTransport = GetDebugServiceTransport(),
diff --git a/src/PowerShellEditorServices.Hosting/Configuration/EditorServicesConfig.cs b/src/PowerShellEditorServices.Hosting/Configuration/EditorServicesConfig.cs
index 3ec99db46..b2e683a2f 100644
--- a/src/PowerShellEditorServices.Hosting/Configuration/EditorServicesConfig.cs
+++ b/src/PowerShellEditorServices.Hosting/Configuration/EditorServicesConfig.cs
@@ -89,6 +89,11 @@ public EditorServicesConfig(
///
public ConsoleReplKind ConsoleRepl { get; set; } = ConsoleReplKind.None;
+ ///
+ /// Will suppress messages to PSHost (to prevent Stdio clobbering)
+ ///
+ public bool UseNullPSHostUI { get; set; }
+
///
/// The minimum log level to log events with.
///
diff --git a/src/PowerShellEditorServices.Hosting/Internal/EditorServicesRunner.cs b/src/PowerShellEditorServices.Hosting/Internal/EditorServicesRunner.cs
index b9dbb0b2e..8f868d393 100644
--- a/src/PowerShellEditorServices.Hosting/Internal/EditorServicesRunner.cs
+++ b/src/PowerShellEditorServices.Hosting/Internal/EditorServicesRunner.cs
@@ -289,6 +289,7 @@ private HostStartupInfo CreateHostStartupInfo()
_config.LogPath,
(int)_config.LogLevel,
consoleReplEnabled: _config.ConsoleRepl != ConsoleReplKind.None,
+ useNullPSHostUI: _config.UseNullPSHostUI,
usesLegacyReadLine: _config.ConsoleRepl == ConsoleReplKind.LegacyReadLine,
bundledModulePath: _config.BundledModulePath);
}
diff --git a/src/PowerShellEditorServices/Hosting/HostStartupInfo.cs b/src/PowerShellEditorServices/Hosting/HostStartupInfo.cs
index ba241a0ac..964509626 100644
--- a/src/PowerShellEditorServices/Hosting/HostStartupInfo.cs
+++ b/src/PowerShellEditorServices/Hosting/HostStartupInfo.cs
@@ -76,6 +76,11 @@ public sealed class HostStartupInfo
///
public bool ConsoleReplEnabled { get; }
+ ///
+ /// True if we want to suppress messages to PSHost (to prevent Stdio clobbering)
+ ///
+ public bool UseNullPSHostUI { get; }
+
///
/// If true, the legacy PSES readline implementation will be used. Otherwise PSReadLine will be used.
/// If the console REPL is not enabled, this setting will be ignored.
@@ -139,6 +144,7 @@ public sealed class HostStartupInfo
/// The path to log to.
/// The minimum log event level.
/// Enable console if true.
+ /// Whether or not to use the Null UI.
/// Use PSReadLine if false, otherwise use the legacy readline implementation.
/// A custom path to the expected bundled modules.
public HostStartupInfo(
@@ -153,6 +159,7 @@ public HostStartupInfo(
string logPath,
int logLevel,
bool consoleReplEnabled,
+ bool useNullPSHostUI,
bool usesLegacyReadLine,
string bundledModulePath)
{
@@ -167,6 +174,7 @@ public HostStartupInfo(
LogPath = logPath;
LogLevel = logLevel;
ConsoleReplEnabled = consoleReplEnabled;
+ UseNullPSHostUI = useNullPSHostUI;
UsesLegacyReadLine = usesLegacyReadLine;
// Respect a user provided bundled module path.
diff --git a/src/PowerShellEditorServices/Services/Analysis/PssaCmdletAnalysisEngine.cs b/src/PowerShellEditorServices/Services/Analysis/PssaCmdletAnalysisEngine.cs
index c460a3020..8875835a7 100644
--- a/src/PowerShellEditorServices/Services/Analysis/PssaCmdletAnalysisEngine.cs
+++ b/src/PowerShellEditorServices/Services/Analysis/PssaCmdletAnalysisEngine.cs
@@ -292,10 +292,17 @@ private PowerShellResult InvokePowerShell(PSCommand command)
catch (CmdletInvocationException ex)
{
// We do not want to crash EditorServices for exceptions caused by cmdlet invocation.
- // Two main reasons that cause the exception are:
+ // The main reasons that cause the exception are:
// * PSCmdlet.WriteOutput being called from another thread than Begin/Process
// * CompositionContainer.ComposeParts complaining that "...Only one batch can be composed at a time"
- _logger.LogError(ex.Message);
+ // * PSScriptAnalyzer not being able to find its PSScriptAnalyzer.psd1 because we are hosted by an Assembly other than pwsh.exe
+ string message = ex.Message;
+ if (!string.IsNullOrEmpty(ex.ErrorRecord.FullyQualifiedErrorId))
+ {
+ // Microsoft.PowerShell.EditorServices.Services.Analysis.PssaCmdletAnalysisEngine: Exception of type 'System.Exception' was thrown. |
+ message += $" | {ex.ErrorRecord.FullyQualifiedErrorId}";
+ }
+ _logger.LogError(message);
}
return result;
diff --git a/src/PowerShellEditorServices/Services/PowerShell/Host/PsesInternalHost.cs b/src/PowerShellEditorServices/Services/PowerShell/Host/PsesInternalHost.cs
index 2b62595c8..c921de81b 100644
--- a/src/PowerShellEditorServices/Services/PowerShell/Host/PsesInternalHost.cs
+++ b/src/PowerShellEditorServices/Services/PowerShell/Host/PsesInternalHost.cs
@@ -193,9 +193,9 @@ public PsesInternalHost(
Version = hostInfo.Version;
DebugContext = new PowerShellDebugContext(loggerFactory, this);
- UI = hostInfo.ConsoleReplEnabled
- ? new EditorServicesConsolePSHostUserInterface(loggerFactory, hostInfo.PSHost.UI)
- : new NullPSHostUI();
+ UI = hostInfo.UseNullPSHostUI
+ ? new NullPSHostUI()
+ : new EditorServicesConsolePSHostUserInterface(loggerFactory, hostInfo.PSHost.UI);
}
public override CultureInfo CurrentCulture => _hostInfo.PSHost.CurrentCulture;
diff --git a/test/PowerShellEditorServices.Test/PsesHostFactory.cs b/test/PowerShellEditorServices.Test/PsesHostFactory.cs
index b2d4ceb7c..0e02b6389 100644
--- a/test/PowerShellEditorServices.Test/PsesHostFactory.cs
+++ b/test/PowerShellEditorServices.Test/PsesHostFactory.cs
@@ -57,6 +57,7 @@ public static PsesInternalHost Create(ILoggerFactory loggerFactory, bool loadPro
logLevel: (int)LogLevel.None,
consoleReplEnabled: false,
usesLegacyReadLine: false,
+ useNullPSHostUI: true,
bundledModulePath: BundledModulePath);
PsesInternalHost psesHost = new(loggerFactory, null, testHostDetails);
diff --git a/test/PowerShellEditorServices.Test/Services/Symbols/PSScriptAnalyzerTests.cs b/test/PowerShellEditorServices.Test/Services/Symbols/PSScriptAnalyzerTests.cs
index b34bbe650..1155db102 100644
--- a/test/PowerShellEditorServices.Test/Services/Symbols/PSScriptAnalyzerTests.cs
+++ b/test/PowerShellEditorServices.Test/Services/Symbols/PSScriptAnalyzerTests.cs
@@ -36,6 +36,7 @@ public class PSScriptAnalyzerTests
logPath: null,
logLevel: 0,
consoleReplEnabled: false,
+ useNullPSHostUI: true,
usesLegacyReadLine: false,
bundledModulePath: PsesHostFactory.BundledModulePath));