diff --git a/src/PowerShellEditorServices.Host/EditorServicesHost.cs b/src/PowerShellEditorServices.Host/EditorServicesHost.cs
index fd1ebb761..ccabf9ba8 100644
--- a/src/PowerShellEditorServices.Host/EditorServicesHost.cs
+++ b/src/PowerShellEditorServices.Host/EditorServicesHost.cs
@@ -34,6 +34,7 @@ public class EditorServicesHost
{
#region Private Fields
+ private ILogger logger;
private bool enableConsoleRepl;
private HostDetails hostDetails;
private ProfilePaths profilePaths;
@@ -114,7 +115,8 @@ public EditorServicesHost(
/// The minimum level of log messages to be written.
public void StartLogging(string logFilePath, LogLevel logLevel)
{
- Logger.Initialize(logFilePath, logLevel);
+ this.logger = new FileLogger(logFilePath, logLevel);
+ Logger.Initialize(this.logger);
#if CoreCLR
FileVersionInfo fileVersionInfo =
@@ -134,7 +136,7 @@ public void StartLogging(string logFilePath, LogLevel logLevel)
string newLine = Environment.NewLine;
- Logger.Write(
+ this.logger.Write(
LogLevel.Normal,
string.Format(
$"PowerShell Editor Services Host v{fileVersionInfo.FileVersion} starting (pid {Process.GetCurrentProcess().Id})..." + newLine + newLine +
@@ -164,12 +166,13 @@ public void StartLanguageService(int languageServicePort, ProfilePaths profilePa
this.languageServiceListener =
new TcpSocketServerListener(
MessageProtocolType.LanguageServer,
- languageServicePort);
+ languageServicePort,
+ this.logger);
this.languageServiceListener.ClientConnect += this.OnLanguageServiceClientConnect;
this.languageServiceListener.Start();
- Logger.Write(
+ this.logger.Write(
LogLevel.Normal,
string.Format(
"Language service started, listening on port {0}",
@@ -189,7 +192,8 @@ private async void OnLanguageServiceClientConnect(
this.languageServer =
new LanguageServer(
this.editorSession,
- serverChannel);
+ serverChannel,
+ this.logger);
await this.editorSession.PowerShellContext.ImportCommandsModule(
Path.Combine(
@@ -211,12 +215,13 @@ public void StartDebugService(
this.debugServiceListener =
new TcpSocketServerListener(
MessageProtocolType.LanguageServer,
- debugServicePort);
+ debugServicePort,
+ this.logger);
this.debugServiceListener.ClientConnect += OnDebugServiceClientConnect;
this.debugServiceListener.Start();
- Logger.Write(
+ this.logger.Write(
LogLevel.Normal,
string.Format(
"Debug service started, listening on port {0}",
@@ -231,7 +236,8 @@ private async void OnDebugServiceClientConnect(object sender, TcpSocketServerCha
new DebugAdapter(
this.editorSession,
serverChannel,
- false);
+ false,
+ this.logger);
}
else
{
@@ -245,13 +251,14 @@ private async void OnDebugServiceClientConnect(object sender, TcpSocketServerCha
new DebugAdapter(
debugSession,
serverChannel,
- true);
+ true,
+ this.logger);
}
this.debugAdapter.SessionEnded +=
(obj, args) =>
{
- Logger.Write(
+ this.logger.Write(
LogLevel.Normal,
"Previous debug session ended, restarting debug service listener...");
@@ -292,8 +299,8 @@ private EditorSession CreateSession(
ProfilePaths profilePaths,
bool enableConsoleRepl)
{
- EditorSession editorSession = new EditorSession();
- PowerShellContext powerShellContext = new PowerShellContext();
+ EditorSession editorSession = new EditorSession(this.logger);
+ PowerShellContext powerShellContext = new PowerShellContext(this.logger);
ConsoleServicePSHost psHost =
new ConsoleServicePSHost(
@@ -316,8 +323,8 @@ private EditorSession CreateDebugSession(
ProfilePaths profilePaths,
IEditorOperations editorOperations)
{
- EditorSession editorSession = new EditorSession();
- PowerShellContext powerShellContext = new PowerShellContext();
+ EditorSession editorSession = new EditorSession(this.logger);
+ PowerShellContext powerShellContext = new PowerShellContext(this.logger);
ConsoleServicePSHost psHost =
new ConsoleServicePSHost(
@@ -337,12 +344,12 @@ private EditorSession CreateDebugSession(
}
#if !CoreCLR
- static void CurrentDomain_UnhandledException(
+ private void CurrentDomain_UnhandledException(
object sender,
UnhandledExceptionEventArgs e)
{
// Log the exception
- Logger.Write(
+ this.logger.Write(
LogLevel.Error,
string.Format(
"FATAL UNHANDLED EXCEPTION:\r\n\r\n{0}",
diff --git a/src/PowerShellEditorServices.Protocol/Client/DebugAdapterClientBase.cs b/src/PowerShellEditorServices.Protocol/Client/DebugAdapterClientBase.cs
index 243543841..aeab98bd8 100644
--- a/src/PowerShellEditorServices.Protocol/Client/DebugAdapterClientBase.cs
+++ b/src/PowerShellEditorServices.Protocol/Client/DebugAdapterClientBase.cs
@@ -7,16 +7,18 @@
using Microsoft.PowerShell.EditorServices.Protocol.MessageProtocol;
using Microsoft.PowerShell.EditorServices.Protocol.MessageProtocol.Channel;
using System.Threading.Tasks;
+using Microsoft.PowerShell.EditorServices.Utility;
namespace Microsoft.PowerShell.EditorServices.Protocol.Client
{
public class DebugAdapterClient : ProtocolEndpoint
{
- public DebugAdapterClient(ChannelBase clientChannel)
+ public DebugAdapterClient(ChannelBase clientChannel, ILogger logger)
: base(
clientChannel,
- new MessageDispatcher(),
- MessageProtocolType.DebugAdapter)
+ new MessageDispatcher(logger),
+ MessageProtocolType.DebugAdapter,
+ logger)
{
}
diff --git a/src/PowerShellEditorServices.Protocol/Client/LanguageClientBase.cs b/src/PowerShellEditorServices.Protocol/Client/LanguageClientBase.cs
index 7611109aa..e7d780263 100644
--- a/src/PowerShellEditorServices.Protocol/Client/LanguageClientBase.cs
+++ b/src/PowerShellEditorServices.Protocol/Client/LanguageClientBase.cs
@@ -7,6 +7,7 @@
using Microsoft.PowerShell.EditorServices.Protocol.MessageProtocol;
using Microsoft.PowerShell.EditorServices.Protocol.MessageProtocol.Channel;
using System.Threading.Tasks;
+using Microsoft.PowerShell.EditorServices.Utility;
namespace Microsoft.PowerShell.EditorServices.Protocol.Client
{
@@ -20,11 +21,12 @@ public abstract class LanguageClientBase : ProtocolEndpoint
/// specified channel for communication.
///
/// The channel to use for communication with the server.
- public LanguageClientBase(ChannelBase clientChannel)
+ public LanguageClientBase(ChannelBase clientChannel, ILogger logger)
: base(
clientChannel,
- new MessageDispatcher(),
- MessageProtocolType.LanguageServer)
+ new MessageDispatcher(logger),
+ MessageProtocolType.LanguageServer,
+ logger)
{
}
diff --git a/src/PowerShellEditorServices.Protocol/Client/LanguageServiceClient.cs b/src/PowerShellEditorServices.Protocol/Client/LanguageServiceClient.cs
index 6c75eebd5..119fd09f8 100644
--- a/src/PowerShellEditorServices.Protocol/Client/LanguageServiceClient.cs
+++ b/src/PowerShellEditorServices.Protocol/Client/LanguageServiceClient.cs
@@ -10,6 +10,7 @@
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
+using Microsoft.PowerShell.EditorServices.Utility;
namespace Microsoft.PowerShell.EditorServices.Protocol.Client
{
@@ -18,8 +19,8 @@ public class LanguageServiceClient : LanguageClientBase
private Dictionary cachedDiagnostics =
new Dictionary();
- public LanguageServiceClient(ChannelBase clientChannel)
- : base(clientChannel)
+ public LanguageServiceClient(ChannelBase clientChannel, ILogger logger)
+ : base(clientChannel, logger)
{
}
diff --git a/src/PowerShellEditorServices.Protocol/MessageProtocol/Channel/NamedPipeClientChannel.cs b/src/PowerShellEditorServices.Protocol/MessageProtocol/Channel/NamedPipeClientChannel.cs
index 68fe5387b..5477ec8b6 100644
--- a/src/PowerShellEditorServices.Protocol/MessageProtocol/Channel/NamedPipeClientChannel.cs
+++ b/src/PowerShellEditorServices.Protocol/MessageProtocol/Channel/NamedPipeClientChannel.cs
@@ -6,16 +6,21 @@
using System;
using System.IO.Pipes;
using System.Threading.Tasks;
+using Microsoft.PowerShell.EditorServices.Utility;
namespace Microsoft.PowerShell.EditorServices.Protocol.MessageProtocol.Channel
{
public class NamedPipeClientChannel : ChannelBase
{
+ private ILogger logger;
private NamedPipeClientStream pipeClient;
- public NamedPipeClientChannel(NamedPipeClientStream pipeClient)
+ public NamedPipeClientChannel(
+ NamedPipeClientStream pipeClient,
+ ILogger logger)
{
this.pipeClient = pipeClient;
+ this.logger = logger;
}
protected override void Initialize(IMessageSerializer messageSerializer)
@@ -23,12 +28,14 @@ protected override void Initialize(IMessageSerializer messageSerializer)
this.MessageReader =
new MessageReader(
this.pipeClient,
- messageSerializer);
+ messageSerializer,
+ this.logger);
this.MessageWriter =
new MessageWriter(
this.pipeClient,
- messageSerializer);
+ messageSerializer,
+ this.logger);
}
protected override void Shutdown()
@@ -41,7 +48,8 @@ protected override void Shutdown()
public static async Task Connect(
string pipeName,
- MessageProtocolType messageProtocolType)
+ MessageProtocolType messageProtocolType,
+ ILogger logger)
{
var pipeClient =
new NamedPipeClientStream(
@@ -68,7 +76,7 @@ public static async Task Connect(
}
}
#endif
- var clientChannel = new NamedPipeClientChannel(pipeClient);
+ var clientChannel = new NamedPipeClientChannel(pipeClient, logger);
clientChannel.Start(messageProtocolType);
return clientChannel;
diff --git a/src/PowerShellEditorServices.Protocol/MessageProtocol/Channel/NamedPipeServerChannel.cs b/src/PowerShellEditorServices.Protocol/MessageProtocol/Channel/NamedPipeServerChannel.cs
index 080b835eb..ad4e01de9 100644
--- a/src/PowerShellEditorServices.Protocol/MessageProtocol/Channel/NamedPipeServerChannel.cs
+++ b/src/PowerShellEditorServices.Protocol/MessageProtocol/Channel/NamedPipeServerChannel.cs
@@ -10,11 +10,15 @@ namespace Microsoft.PowerShell.EditorServices.Protocol.MessageProtocol.Channel
{
public class NamedPipeServerChannel : ChannelBase
{
+ private ILogger logger;
private NamedPipeServerStream pipeServer;
- public NamedPipeServerChannel(NamedPipeServerStream pipeServer)
+ public NamedPipeServerChannel(
+ NamedPipeServerStream pipeServer,
+ ILogger logger)
{
this.pipeServer = pipeServer;
+ this.logger = logger;
}
protected override void Initialize(IMessageSerializer messageSerializer)
@@ -22,12 +26,14 @@ protected override void Initialize(IMessageSerializer messageSerializer)
this.MessageReader =
new MessageReader(
this.pipeServer,
- messageSerializer);
+ messageSerializer,
+ this.logger);
this.MessageWriter =
new MessageWriter(
this.pipeServer,
- messageSerializer);
+ messageSerializer,
+ this.logger);
}
protected override void Shutdown()
diff --git a/src/PowerShellEditorServices.Protocol/MessageProtocol/Channel/NamedPipeServerListener.cs b/src/PowerShellEditorServices.Protocol/MessageProtocol/Channel/NamedPipeServerListener.cs
index 99dbb00fb..cf1cb3e4c 100644
--- a/src/PowerShellEditorServices.Protocol/MessageProtocol/Channel/NamedPipeServerListener.cs
+++ b/src/PowerShellEditorServices.Protocol/MessageProtocol/Channel/NamedPipeServerListener.cs
@@ -13,14 +13,17 @@ namespace Microsoft.PowerShell.EditorServices.Protocol.MessageProtocol.Channel
{
public class NamedPipeServerListener : ServerListenerBase
{
+ private ILogger logger;
private string pipeName;
private NamedPipeServerStream pipeServer;
public NamedPipeServerListener(
MessageProtocolType messageProtocolType,
- string pipeName)
+ string pipeName,
+ ILogger logger)
: base(messageProtocolType)
{
+ this.logger = logger;
this.pipeName = pipeName;
}
@@ -38,7 +41,7 @@ public override void Start()
}
catch (IOException e)
{
- Logger.Write(
+ this.logger.Write(
LogLevel.Verbose,
"Named pipe server failed to start due to exception:\r\n\r\n" + e.Message);
@@ -50,11 +53,11 @@ public override void Stop()
{
if (this.pipeServer != null)
{
- Logger.Write(LogLevel.Verbose, "Named pipe server shutting down...");
+ this.logger.Write(LogLevel.Verbose, "Named pipe server shutting down...");
this.pipeServer.Dispose();
- Logger.Write(LogLevel.Verbose, "Named pipe server has been disposed.");
+ this.logger.Write(LogLevel.Verbose, "Named pipe server has been disposed.");
}
}
@@ -69,16 +72,17 @@ private void ListenForConnection()
await this.pipeServer.WaitForConnectionAsync();
#else
await Task.Factory.FromAsync(
- this.pipeServer.BeginWaitForConnection,
+ this.pipeServer.BeginWaitForConnection,
this.pipeServer.EndWaitForConnection, null);
#endif
this.OnClientConnect(
new NamedPipeServerChannel(
- this.pipeServer));
+ this.pipeServer,
+ this.logger));
}
catch (Exception e)
{
- Logger.WriteException(
+ this.logger.WriteException(
"An unhandled exception occurred while listening for a named pipe client connection",
e);
diff --git a/src/PowerShellEditorServices.Protocol/MessageProtocol/Channel/StdioClientChannel.cs b/src/PowerShellEditorServices.Protocol/MessageProtocol/Channel/StdioClientChannel.cs
index b262afa57..86fe7ce7a 100644
--- a/src/PowerShellEditorServices.Protocol/MessageProtocol/Channel/StdioClientChannel.cs
+++ b/src/PowerShellEditorServices.Protocol/MessageProtocol/Channel/StdioClientChannel.cs
@@ -6,6 +6,7 @@
using System.Diagnostics;
using System.IO;
using System.Text;
+using Microsoft.PowerShell.EditorServices.Utility;
namespace Microsoft.PowerShell.EditorServices.Protocol.MessageProtocol.Channel
{
@@ -19,6 +20,7 @@ public class StdioClientChannel : ChannelBase
private string serviceProcessPath;
private string serviceProcessArguments;
+ private ILogger logger;
private Stream inputStream;
private Stream outputStream;
private Process serviceProcess;
@@ -35,8 +37,10 @@ public class StdioClientChannel : ChannelBase
/// Optional arguments to pass to the service process executable.
public StdioClientChannel(
string serverProcessPath,
+ ILogger logger,
params string[] serverProcessArguments)
{
+ this.logger = logger;
this.serviceProcessPath = serverProcessPath;
if (serverProcessArguments != null)
@@ -48,11 +52,6 @@ public StdioClientChannel(
}
}
- public StdioClientChannel(Process serviceProcess)
- {
- this.serviceProcess = serviceProcess;
- }
-
protected override void Initialize(IMessageSerializer messageSerializer)
{
this.serviceProcess = new Process
@@ -84,12 +83,14 @@ protected override void Initialize(IMessageSerializer messageSerializer)
this.MessageReader =
new MessageReader(
this.inputStream,
- messageSerializer);
+ messageSerializer,
+ this.logger);
this.MessageWriter =
new MessageWriter(
this.outputStream,
- messageSerializer);
+ messageSerializer,
+ this.logger);
}
protected override void Shutdown()
diff --git a/src/PowerShellEditorServices.Protocol/MessageProtocol/Channel/StdioServerChannel.cs b/src/PowerShellEditorServices.Protocol/MessageProtocol/Channel/StdioServerChannel.cs
index 9431639cf..119f42110 100644
--- a/src/PowerShellEditorServices.Protocol/MessageProtocol/Channel/StdioServerChannel.cs
+++ b/src/PowerShellEditorServices.Protocol/MessageProtocol/Channel/StdioServerChannel.cs
@@ -5,6 +5,7 @@
using System.IO;
using System.Text;
+using Microsoft.PowerShell.EditorServices.Utility;
namespace Microsoft.PowerShell.EditorServices.Protocol.MessageProtocol.Channel
{
@@ -15,9 +16,15 @@ namespace Microsoft.PowerShell.EditorServices.Protocol.MessageProtocol.Channel
///
public class StdioServerChannel : ChannelBase
{
+ private ILogger logger;
private Stream inputStream;
private Stream outputStream;
+ public StdioServerChannel(ILogger logger)
+ {
+ this.logger = logger;
+ }
+
protected override void Initialize(IMessageSerializer messageSerializer)
{
#if !CoreCLR
@@ -34,12 +41,14 @@ protected override void Initialize(IMessageSerializer messageSerializer)
this.MessageReader =
new MessageReader(
this.inputStream,
- messageSerializer);
+ messageSerializer,
+ this.logger);
this.MessageWriter =
new MessageWriter(
this.outputStream,
- messageSerializer);
+ messageSerializer,
+ this.logger);
}
protected override void Shutdown()
diff --git a/src/PowerShellEditorServices.Protocol/MessageProtocol/Channel/StdioServerListener.cs b/src/PowerShellEditorServices.Protocol/MessageProtocol/Channel/StdioServerListener.cs
index 3097c831a..6b850035d 100644
--- a/src/PowerShellEditorServices.Protocol/MessageProtocol/Channel/StdioServerListener.cs
+++ b/src/PowerShellEditorServices.Protocol/MessageProtocol/Channel/StdioServerListener.cs
@@ -4,21 +4,29 @@
//
using System.IO;
+using Microsoft.PowerShell.EditorServices.Utility;
namespace Microsoft.PowerShell.EditorServices.Protocol.MessageProtocol.Channel
{
public class StdioServerListener : ServerListenerBase
{
- public StdioServerListener(MessageProtocolType messageProtocolType) :
- base(messageProtocolType)
+ private ILogger logger;
+
+ public StdioServerListener(
+ MessageProtocolType messageProtocolType,
+ ILogger logger)
+ : base(messageProtocolType)
{
+ this.logger = logger;
}
public override void Start()
{
// Client is connected immediately because stdio
// will buffer all I/O until we get to it
- this.OnClientConnect(new StdioServerChannel());
+ this.OnClientConnect(
+ new StdioServerChannel(
+ this.logger));
}
public override void Stop()
diff --git a/src/PowerShellEditorServices.Protocol/MessageProtocol/Channel/TcpSocketClientChannel.cs b/src/PowerShellEditorServices.Protocol/MessageProtocol/Channel/TcpSocketClientChannel.cs
index a0baf9e51..f331d6879 100644
--- a/src/PowerShellEditorServices.Protocol/MessageProtocol/Channel/TcpSocketClientChannel.cs
+++ b/src/PowerShellEditorServices.Protocol/MessageProtocol/Channel/TcpSocketClientChannel.cs
@@ -6,16 +6,21 @@
using System.Net;
using System.Net.Sockets;
using System.Threading.Tasks;
+using Microsoft.PowerShell.EditorServices.Utility;
namespace Microsoft.PowerShell.EditorServices.Protocol.MessageProtocol.Channel
{
public class TcpSocketClientChannel : ChannelBase
{
+ private ILogger logger;
private NetworkStream networkStream;
- public TcpSocketClientChannel(TcpClient tcpClient)
+ public TcpSocketClientChannel(
+ TcpClient tcpClient,
+ ILogger logger)
{
this.networkStream = tcpClient.GetStream();
+ this.logger = logger;
}
protected override void Initialize(IMessageSerializer messageSerializer)
@@ -23,12 +28,14 @@ protected override void Initialize(IMessageSerializer messageSerializer)
this.MessageReader =
new MessageReader(
this.networkStream,
- messageSerializer);
+ messageSerializer,
+ this.logger);
this.MessageWriter =
new MessageWriter(
this.networkStream,
- messageSerializer);
+ messageSerializer,
+ this.logger);
}
protected override void Shutdown()
@@ -42,12 +49,13 @@ protected override void Shutdown()
public static async Task Connect(
int portNumber,
- MessageProtocolType messageProtocolType)
+ MessageProtocolType messageProtocolType,
+ ILogger logger)
{
TcpClient tcpClient = new TcpClient();
await tcpClient.ConnectAsync(IPAddress.Loopback, portNumber);
- var clientChannel = new TcpSocketClientChannel(tcpClient);
+ var clientChannel = new TcpSocketClientChannel(tcpClient, logger);
clientChannel.Start(messageProtocolType);
return clientChannel;
diff --git a/src/PowerShellEditorServices.Protocol/MessageProtocol/Channel/TcpSocketServerChannel.cs b/src/PowerShellEditorServices.Protocol/MessageProtocol/Channel/TcpSocketServerChannel.cs
index df702046e..b41deb75b 100755
--- a/src/PowerShellEditorServices.Protocol/MessageProtocol/Channel/TcpSocketServerChannel.cs
+++ b/src/PowerShellEditorServices.Protocol/MessageProtocol/Channel/TcpSocketServerChannel.cs
@@ -12,13 +12,15 @@ namespace Microsoft.PowerShell.EditorServices.Protocol.MessageProtocol.Channel
{
public class TcpSocketServerChannel : ChannelBase
{
+ private ILogger logger;
private TcpClient tcpClient;
private NetworkStream networkStream;
- public TcpSocketServerChannel(TcpClient tcpClient)
+ public TcpSocketServerChannel(TcpClient tcpClient, ILogger logger)
{
this.tcpClient = tcpClient;
this.networkStream = this.tcpClient.GetStream();
+ this.logger = logger;
}
protected override void Initialize(IMessageSerializer messageSerializer)
@@ -26,12 +28,14 @@ protected override void Initialize(IMessageSerializer messageSerializer)
this.MessageReader =
new MessageReader(
this.networkStream,
- messageSerializer);
+ messageSerializer,
+ this.logger);
this.MessageWriter =
new MessageWriter(
this.networkStream,
- messageSerializer);
+ messageSerializer,
+ this.logger);
}
protected override void Shutdown()
@@ -47,7 +51,7 @@ protected override void Shutdown()
#endif
this.tcpClient = null;
- Logger.Write(LogLevel.Verbose, "TCP client has been closed");
+ this.logger.Write(LogLevel.Verbose, "TCP client has been closed");
}
}
}
diff --git a/src/PowerShellEditorServices.Protocol/MessageProtocol/Channel/TcpSocketServerListener.cs b/src/PowerShellEditorServices.Protocol/MessageProtocol/Channel/TcpSocketServerListener.cs
index bb5266454..9299b51e2 100644
--- a/src/PowerShellEditorServices.Protocol/MessageProtocol/Channel/TcpSocketServerListener.cs
+++ b/src/PowerShellEditorServices.Protocol/MessageProtocol/Channel/TcpSocketServerListener.cs
@@ -13,15 +13,18 @@ namespace Microsoft.PowerShell.EditorServices.Protocol.MessageProtocol.Channel
{
public class TcpSocketServerListener : ServerListenerBase
{
+ private ILogger logger;
private int portNumber;
private TcpListener tcpListener;
public TcpSocketServerListener(
MessageProtocolType messageProtocolType,
- int portNumber)
+ int portNumber,
+ ILogger logger)
: base(messageProtocolType)
{
this.portNumber = portNumber;
+ this.logger = logger;
}
public override void Start()
@@ -43,7 +46,7 @@ public override void Stop()
this.tcpListener.Stop();
this.tcpListener = null;
- Logger.Write(LogLevel.Verbose, "TCP listener has been stopped");
+ this.logger.Write(LogLevel.Verbose, "TCP listener has been stopped");
}
}
@@ -57,11 +60,12 @@ private void ListenForConnection()
TcpClient tcpClient = await this.tcpListener.AcceptTcpClientAsync();
this.OnClientConnect(
new TcpSocketServerChannel(
- tcpClient));
+ tcpClient,
+ this.logger));
}
catch (Exception e)
{
- Logger.WriteException(
+ this.logger.WriteException(
"An unhandled exception occurred while listening for a TCP client connection",
e);
diff --git a/src/PowerShellEditorServices.Protocol/MessageProtocol/MessageDispatcher.cs b/src/PowerShellEditorServices.Protocol/MessageProtocol/MessageDispatcher.cs
index 5b04c5f03..4338ca3b3 100644
--- a/src/PowerShellEditorServices.Protocol/MessageProtocol/MessageDispatcher.cs
+++ b/src/PowerShellEditorServices.Protocol/MessageProtocol/MessageDispatcher.cs
@@ -17,6 +17,8 @@ public class MessageDispatcher
{
#region Fields
+ private ILogger logger;
+
private Dictionary> requestHandlers =
new Dictionary>();
@@ -25,6 +27,15 @@ public class MessageDispatcher
#endregion
+ #region Constructors
+
+ public MessageDispatcher(ILogger logger)
+ {
+ this.logger = logger;
+ }
+
+ #endregion
+
#region Public Methods
public void SetRequestHandler(
@@ -126,7 +137,7 @@ public async Task DispatchMessage(
else
{
// TODO: Message not supported error
- Logger.Write(LogLevel.Error, $"MessageDispatcher: No handler registered for Request type '{messageToDispatch.Method}'");
+ this.logger.Write(LogLevel.Error, $"MessageDispatcher: No handler registered for Request type '{messageToDispatch.Method}'");
}
}
else if (messageToDispatch.MessageType == MessageType.Event)
@@ -139,13 +150,13 @@ public async Task DispatchMessage(
else
{
// TODO: Message not supported error
- Logger.Write(LogLevel.Error, $"MessageDispatcher: No handler registered for Event type '{messageToDispatch.Method}'");
+ this.logger.Write(LogLevel.Error, $"MessageDispatcher: No handler registered for Event type '{messageToDispatch.Method}'");
}
}
else
{
// TODO: Return message not supported
- Logger.Write(LogLevel.Error, $"MessageDispatcher received unknown message type of method '{messageToDispatch.Method}'");
+ this.logger.Write(LogLevel.Error, $"MessageDispatcher received unknown message type of method '{messageToDispatch.Method}'");
}
if (handlerToAwait != null)
diff --git a/src/PowerShellEditorServices.Protocol/MessageProtocol/MessageReader.cs b/src/PowerShellEditorServices.Protocol/MessageProtocol/MessageReader.cs
index 32ec9387f..5323774f8 100644
--- a/src/PowerShellEditorServices.Protocol/MessageProtocol/MessageReader.cs
+++ b/src/PowerShellEditorServices.Protocol/MessageProtocol/MessageReader.cs
@@ -23,8 +23,9 @@ public class MessageReader
private const int CR = 0x0D;
private const int LF = 0x0A;
- private static string[] NewLineDelimiters = new string[] { Environment.NewLine };
+ private static string[] NewLineDelimiters = new string[] { Environment.NewLine };
+ private ILogger logger;
private Stream inputStream;
private IMessageSerializer messageSerializer;
private Encoding messageEncoding;
@@ -51,11 +52,13 @@ enum ReadState
public MessageReader(
Stream inputStream,
IMessageSerializer messageSerializer,
+ ILogger logger,
Encoding messageEncoding = null)
{
Validate.IsNotNull("streamReader", inputStream);
Validate.IsNotNull("messageSerializer", messageSerializer);
+ this.logger = logger;
this.inputStream = inputStream;
this.messageSerializer = messageSerializer;
@@ -83,7 +86,7 @@ public async Task ReadMessage()
this.needsMoreData = false;
// Do we need to look for message headers?
- if (this.readState == ReadState.Headers &&
+ if (this.readState == ReadState.Headers &&
!this.TryReadMessageHeaders())
{
// If we don't have enough data to read headers yet, keep reading
@@ -92,7 +95,7 @@ public async Task ReadMessage()
}
// Do we need to look for message content?
- if (this.readState == ReadState.Content &&
+ if (this.readState == ReadState.Content &&
!this.TryReadMessageContent(out messageContent))
{
// If we don't have enough data yet to construct the content, keep reading
@@ -108,7 +111,7 @@ public async Task ReadMessage()
JObject messageObject = JObject.Parse(messageContent);
// Load the message
- Logger.Write(
+ this.logger.Write(
LogLevel.Verbose,
string.Format(
"READ MESSAGE:\r\n\r\n{0}",
@@ -129,7 +132,7 @@ private async Task ReadNextChunk()
{
// Double the size of the buffer
Array.Resize(
- ref this.messageBuffer,
+ ref this.messageBuffer,
this.messageBuffer.Length * 2);
}
@@ -162,10 +165,10 @@ private bool TryReadMessageHeaders()
// Scan for the final double-newline that marks the
// end of the header lines
- while (scanOffset + 3 < this.bufferEndOffset &&
- (this.messageBuffer[scanOffset] != CR ||
- this.messageBuffer[scanOffset + 1] != LF ||
- this.messageBuffer[scanOffset + 2] != CR ||
+ while (scanOffset + 3 < this.bufferEndOffset &&
+ (this.messageBuffer[scanOffset] != CR ||
+ this.messageBuffer[scanOffset + 1] != LF ||
+ this.messageBuffer[scanOffset + 2] != CR ||
this.messageBuffer[scanOffset + 3] != LF))
{
scanOffset++;
@@ -179,7 +182,7 @@ private bool TryReadMessageHeaders()
this.messageHeaders = new Dictionary();
- var headers =
+ var headers =
Encoding.ASCII
.GetString(this.messageBuffer, this.readOffset, scanOffset)
.Split(NewLineDelimiters, StringSplitOptions.RemoveEmptyEntries);
@@ -232,19 +235,19 @@ private bool TryReadMessageContent(out string messageContent)
}
// Convert the message contents to a string using the specified encoding
- messageContent =
+ messageContent =
this.messageEncoding.GetString(
this.messageBuffer,
- this.readOffset,
+ this.readOffset,
this.expectedContentLength);
// Move the remaining bytes to the front of the buffer for the next message
var remainingByteCount = this.bufferEndOffset - (this.expectedContentLength + this.readOffset);
Buffer.BlockCopy(
- this.messageBuffer,
- this.expectedContentLength + this.readOffset,
- this.messageBuffer,
- 0,
+ this.messageBuffer,
+ this.expectedContentLength + this.readOffset,
+ this.messageBuffer,
+ 0,
remainingByteCount);
// Reset the offsets for the next read
diff --git a/src/PowerShellEditorServices.Protocol/MessageProtocol/MessageWriter.cs b/src/PowerShellEditorServices.Protocol/MessageProtocol/MessageWriter.cs
index b1936d40e..e196472f0 100644
--- a/src/PowerShellEditorServices.Protocol/MessageProtocol/MessageWriter.cs
+++ b/src/PowerShellEditorServices.Protocol/MessageProtocol/MessageWriter.cs
@@ -17,6 +17,7 @@ public class MessageWriter
{
#region Private Fields
+ private ILogger logger;
private Stream outputStream;
private IMessageSerializer messageSerializer;
private AsyncLock writeLock = new AsyncLock();
@@ -31,11 +32,13 @@ public class MessageWriter
public MessageWriter(
Stream outputStream,
- IMessageSerializer messageSerializer)
+ IMessageSerializer messageSerializer,
+ ILogger logger)
{
Validate.IsNotNull("streamWriter", outputStream);
Validate.IsNotNull("messageSerializer", messageSerializer);
+ this.logger = logger;
this.outputStream = outputStream;
this.messageSerializer = messageSerializer;
}
@@ -56,7 +59,7 @@ public async Task WriteMessage(Message messageToWrite)
messageToWrite);
// Log the JSON representation of the message
- Logger.Write(
+ this.logger.Write(
LogLevel.Verbose,
string.Format(
"WRITE MESSAGE:\r\n\r\n{0}",
diff --git a/src/PowerShellEditorServices.Protocol/MessageProtocol/ProtocolEndpoint.cs b/src/PowerShellEditorServices.Protocol/MessageProtocol/ProtocolEndpoint.cs
index cbb9f60fd..4a11d4eec 100644
--- a/src/PowerShellEditorServices.Protocol/MessageProtocol/ProtocolEndpoint.cs
+++ b/src/PowerShellEditorServices.Protocol/MessageProtocol/ProtocolEndpoint.cs
@@ -52,6 +52,8 @@ private bool InMessageLoopThread
}
}
+ protected ILogger Logger { get; private set; }
+
///
/// Gets the MessageDispatcher which allows registration of
/// handlers for requests, responses, and events that are
@@ -72,12 +74,14 @@ private bool InMessageLoopThread
public ProtocolEndpoint(
ChannelBase protocolChannel,
MessageDispatcher messageDispatcher,
- MessageProtocolType messageProtocolType)
+ MessageProtocolType messageProtocolType,
+ ILogger logger)
{
this.protocolChannel = protocolChannel;
this.MessageDispatcher = messageDispatcher;
this.messageProtocolType = messageProtocolType;
this.originalSynchronizationContext = SynchronizationContext.Current;
+ this.Logger = logger;
}
///
@@ -94,7 +98,7 @@ public async Task Start()
// Listen for unhandled exceptions from the message loop
this.UnhandledException += MessageDispatcher_UnhandledException;
- // Start the message loop
+ // Start the message loop
this.StartMessageLoop();
// Notify implementation about endpoint start
@@ -317,7 +321,9 @@ private void StartMessageLoop()
// an independent background thread.
this.messageLoopThread = new AsyncContextThread("Message Dispatcher");
this.messageLoopThread
- .Run(() => this.ListenForMessages(this.messageLoopCancellationToken.Token))
+ .Run(
+ () => this.ListenForMessages(this.messageLoopCancellationToken.Token),
+ this.Logger)
.ContinueWith(this.OnListenTaskCompleted);
}
diff --git a/src/PowerShellEditorServices.Protocol/Server/DebugAdapter.cs b/src/PowerShellEditorServices.Protocol/Server/DebugAdapter.cs
index 8b48ddeb4..56200d1db 100644
--- a/src/PowerShellEditorServices.Protocol/Server/DebugAdapter.cs
+++ b/src/PowerShellEditorServices.Protocol/Server/DebugAdapter.cs
@@ -40,8 +40,9 @@ public class DebugAdapter : DebugAdapterBase
public DebugAdapter(
EditorSession editorSession,
ChannelBase serverChannel,
- bool ownsEditorSession)
- : base(serverChannel, new MessageDispatcher())
+ bool ownsEditorSession,
+ ILogger logger)
+ : base(serverChannel, new MessageDispatcher(logger), logger)
{
this.editorSession = editorSession;
this.ownsEditorSession = ownsEditorSession;
diff --git a/src/PowerShellEditorServices.Protocol/Server/DebugAdapterBase.cs b/src/PowerShellEditorServices.Protocol/Server/DebugAdapterBase.cs
index d6c0485c8..b804ed0fe 100644
--- a/src/PowerShellEditorServices.Protocol/Server/DebugAdapterBase.cs
+++ b/src/PowerShellEditorServices.Protocol/Server/DebugAdapterBase.cs
@@ -7,6 +7,7 @@
using Microsoft.PowerShell.EditorServices.Protocol.MessageProtocol;
using Microsoft.PowerShell.EditorServices.Protocol.MessageProtocol.Channel;
using System.Threading.Tasks;
+using Microsoft.PowerShell.EditorServices.Utility;
namespace Microsoft.PowerShell.EditorServices.Protocol.Server
{
@@ -14,11 +15,13 @@ public abstract class DebugAdapterBase : ProtocolEndpoint
{
public DebugAdapterBase(
ChannelBase serverChannel,
- MessageDispatcher messageDispatcher)
+ MessageDispatcher messageDispatcher,
+ ILogger logger)
: base(
serverChannel,
messageDispatcher,
- MessageProtocolType.DebugAdapter)
+ MessageProtocolType.DebugAdapter,
+ logger)
{
}
diff --git a/src/PowerShellEditorServices.Protocol/Server/LanguageServer.cs b/src/PowerShellEditorServices.Protocol/Server/LanguageServer.cs
index 3854b8506..a528aad2f 100644
--- a/src/PowerShellEditorServices.Protocol/Server/LanguageServer.cs
+++ b/src/PowerShellEditorServices.Protocol/Server/LanguageServer.cs
@@ -49,8 +49,9 @@ public IEditorOperations EditorOperations
///
public LanguageServer(
EditorSession editorSession,
- ChannelBase serverChannel)
- : base(serverChannel, new MessageDispatcher())
+ ChannelBase serverChannel,
+ ILogger logger)
+ : base(serverChannel, new MessageDispatcher(logger), logger)
{
this.editorSession = editorSession;
this.editorSession.PowerShellContext.RunspaceChanged += PowerShellContext_RunspaceChanged;
@@ -560,7 +561,8 @@ protected async Task HandleDidChangeConfigurationNotification(
this.currentSettings.Update(
configChangeParams.Settings.Powershell,
- this.editorSession.Workspace.WorkspacePath);
+ this.editorSession.Workspace.WorkspacePath,
+ this.Logger);
if (!this.profilesLoaded &&
this.currentSettings.EnableProfileLoading &&
@@ -1342,6 +1344,7 @@ private Task RunScriptDiagnostics(
this.codeActionsPerFile,
editorSession,
eventSender,
+ this.Logger,
existingRequestCancellation.Token),
CancellationToken.None,
TaskCreationOptions.None,
@@ -1357,6 +1360,7 @@ private static async Task DelayThenInvokeDiagnostics(
Dictionary> correctionIndex,
EditorSession editorSession,
EventContext eventContext,
+ ILogger Logger,
CancellationToken cancellationToken)
{
await DelayThenInvokeDiagnostics(
@@ -1366,6 +1370,7 @@ await DelayThenInvokeDiagnostics(
correctionIndex,
editorSession,
eventContext.SendEvent,
+ Logger,
cancellationToken);
}
@@ -1377,6 +1382,7 @@ private static async Task DelayThenInvokeDiagnostics(
Dictionary> correctionIndex,
EditorSession editorSession,
Func, PublishDiagnosticsNotification, Task> eventSender,
+ ILogger Logger,
CancellationToken cancellationToken)
{
// First of all, wait for the desired delay period before
diff --git a/src/PowerShellEditorServices.Protocol/Server/LanguageServerBase.cs b/src/PowerShellEditorServices.Protocol/Server/LanguageServerBase.cs
index 7846b37d7..869895e43 100644
--- a/src/PowerShellEditorServices.Protocol/Server/LanguageServerBase.cs
+++ b/src/PowerShellEditorServices.Protocol/Server/LanguageServerBase.cs
@@ -6,6 +6,7 @@
using Microsoft.PowerShell.EditorServices.Protocol.LanguageServer;
using Microsoft.PowerShell.EditorServices.Protocol.MessageProtocol;
using Microsoft.PowerShell.EditorServices.Protocol.MessageProtocol.Channel;
+using Microsoft.PowerShell.EditorServices.Utility;
using System.Threading.Tasks;
namespace Microsoft.PowerShell.EditorServices.Protocol.Server
@@ -16,11 +17,13 @@ public abstract class LanguageServerBase : ProtocolEndpoint
public LanguageServerBase(
ChannelBase serverChannel,
- MessageDispatcher messageDispatcher)
+ MessageDispatcher messageDispatcher,
+ ILogger logger)
: base(
serverChannel,
messageDispatcher,
- MessageProtocolType.LanguageServer)
+ MessageProtocolType.LanguageServer,
+ logger)
{
this.serverChannel = serverChannel;
}
diff --git a/src/PowerShellEditorServices.Protocol/Server/LanguageServerSettings.cs b/src/PowerShellEditorServices.Protocol/Server/LanguageServerSettings.cs
index cb90268cb..55879e8a3 100644
--- a/src/PowerShellEditorServices.Protocol/Server/LanguageServerSettings.cs
+++ b/src/PowerShellEditorServices.Protocol/Server/LanguageServerSettings.cs
@@ -19,12 +19,18 @@ public LanguageServerSettings()
this.ScriptAnalysis = new ScriptAnalysisSettings();
}
- public void Update(LanguageServerSettings settings, string workspaceRootPath)
+ public void Update(
+ LanguageServerSettings settings,
+ string workspaceRootPath,
+ ILogger logger)
{
if (settings != null)
{
this.EnableProfileLoading = settings.EnableProfileLoading;
- this.ScriptAnalysis.Update(settings.ScriptAnalysis, workspaceRootPath);
+ this.ScriptAnalysis.Update(
+ settings.ScriptAnalysis,
+ workspaceRootPath,
+ logger);
}
}
}
@@ -40,7 +46,10 @@ public ScriptAnalysisSettings()
this.Enable = true;
}
- public void Update(ScriptAnalysisSettings settings, string workspaceRootPath)
+ public void Update(
+ ScriptAnalysisSettings settings,
+ string workspaceRootPath,
+ ILogger logger)
{
if (settings != null)
{
@@ -62,7 +71,7 @@ public void Update(ScriptAnalysisSettings settings, string workspaceRootPath)
// In this case we should just log an error and let
// the specified settings path go through even though
// it will fail to load.
- Logger.Write(
+ logger.Write(
LogLevel.Error,
"Could not resolve Script Analyzer settings path due to null or empty workspaceRootPath.");
}
diff --git a/src/PowerShellEditorServices.Protocol/Server/PromptHandlers.cs b/src/PowerShellEditorServices.Protocol/Server/PromptHandlers.cs
index ed2433fe1..ff6097c5d 100644
--- a/src/PowerShellEditorServices.Protocol/Server/PromptHandlers.cs
+++ b/src/PowerShellEditorServices.Protocol/Server/PromptHandlers.cs
@@ -31,7 +31,8 @@ public ChoicePromptHandler GetChoicePromptHandler()
{
return new ProtocolChoicePromptHandler(
this.messageSender,
- this.consoleService);
+ this.consoleService,
+ Logger.CurrentLogger);
}
public InputPromptHandler GetInputPromptHandler()
@@ -50,8 +51,9 @@ internal class ProtocolChoicePromptHandler : ConsoleChoicePromptHandler
public ProtocolChoicePromptHandler(
IMessageSender messageSender,
- ConsoleService consoleService)
- : base(consoleService)
+ ConsoleService consoleService,
+ ILogger logger)
+ : base(consoleService, logger)
{
this.messageSender = messageSender;
this.consoleService = consoleService;
@@ -131,7 +133,9 @@ internal class ProtocolInputPromptHandler : ConsoleInputPromptHandler
public ProtocolInputPromptHandler(
IMessageSender messageSender,
ConsoleService consoleService)
- : base(consoleService)
+ : base(
+ consoleService,
+ Microsoft.PowerShell.EditorServices.Utility.Logger.CurrentLogger)
{
this.messageSender = messageSender;
this.consoleService = consoleService;
diff --git a/src/PowerShellEditorServices/Analysis/AnalysisService.cs b/src/PowerShellEditorServices/Analysis/AnalysisService.cs
index 7d14bd4dc..ca6e98f12 100644
--- a/src/PowerShellEditorServices/Analysis/AnalysisService.cs
+++ b/src/PowerShellEditorServices/Analysis/AnalysisService.cs
@@ -25,6 +25,8 @@ public class AnalysisService : IDisposable
#region Private Fields
private const int NumRunspaces = 1;
+
+ private ILogger logger;
private RunspacePool analysisRunspacePool;
private PSModuleInfo scriptAnalyzerModuleInfo;
@@ -103,13 +105,16 @@ public string SettingsPath
/// Creates an instance of the AnalysisService class.
///
/// Path to a PSScriptAnalyzer settings file.
- public AnalysisService(string settingsPath = null)
+ /// An ILogger implementation used for writing log messages.
+ public AnalysisService(string settingsPath, ILogger logger)
{
+ this.logger = logger;
+
try
{
this.SettingsPath = settingsPath;
- scriptAnalyzerModuleInfo = FindPSScriptAnalyzerModule();
+ scriptAnalyzerModuleInfo = FindPSScriptAnalyzerModule(logger);
var sessionState = InitialSessionState.CreateDefault2();
sessionState.ImportPSModulesFromPath(scriptAnalyzerModuleInfo.ModuleBase);
@@ -131,7 +136,7 @@ public AnalysisService(string settingsPath = null)
var sb = new StringBuilder();
sb.AppendLine("PSScriptAnalyzer cannot be imported, AnalysisService will be disabled.");
sb.AppendLine(e.Message);
- Logger.Write(LogLevel.Warning, sb.ToString());
+ this.logger.Write(LogLevel.Warning, sb.ToString());
}
}
@@ -295,7 +300,7 @@ private async Task GetSemanticMarkersAsync(
}
}
- private static PSModuleInfo FindPSScriptAnalyzerModule()
+ private static PSModuleInfo FindPSScriptAnalyzerModule(ILogger logger)
{
using (var ps = System.Management.Automation.PowerShell.Create())
{
@@ -314,7 +319,7 @@ private static PSModuleInfo FindPSScriptAnalyzerModule()
var psModuleInfo = modules == null ? null : modules.FirstOrDefault();
if (psModuleInfo != null)
{
- Logger.Write(
+ logger.Write(
LogLevel.Normal,
string.Format(
"PSScriptAnalyzer found at {0}",
@@ -323,7 +328,7 @@ private static PSModuleInfo FindPSScriptAnalyzerModule()
return psModuleInfo;
}
- Logger.Write(
+ logger.Write(
LogLevel.Normal,
"PSScriptAnalyzer module was not found.");
return null;
@@ -342,7 +347,7 @@ private void EnumeratePSScriptAnalyzerRules()
sb.AppendLine(rule);
}
- Logger.Write(LogLevel.Verbose, sb.ToString());
+ this.logger.Write(LogLevel.Verbose, sb.ToString());
}
}
@@ -380,7 +385,7 @@ private async Task GetDiagnosticRecordsAsync(
});
}
- Logger.Write(
+ this.logger.Write(
LogLevel.Verbose,
String.Format("Found {0} violations", diagnosticRecords.Count()));
@@ -410,7 +415,7 @@ private PSObject[] InvokePowerShell(string command, IDictionary
// Two 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.Write(LogLevel.Error, ex.Message);
+ this.logger.Write(LogLevel.Error, ex.Message);
}
return result;
diff --git a/src/PowerShellEditorServices/Console/ChoicePromptHandler.cs b/src/PowerShellEditorServices/Console/ChoicePromptHandler.cs
index ea0139141..e279c5570 100644
--- a/src/PowerShellEditorServices/Console/ChoicePromptHandler.cs
+++ b/src/PowerShellEditorServices/Console/ChoicePromptHandler.cs
@@ -9,6 +9,7 @@
using System.Management.Automation;
using System.Threading;
using System.Threading.Tasks;
+using Microsoft.PowerShell.EditorServices.Utility;
namespace Microsoft.PowerShell.EditorServices.Console
{
@@ -47,6 +48,14 @@ public abstract class ChoicePromptHandler : PromptHandler
#endregion
+ ///
+ ///
+ ///
+ /// An ILogger implementation used for writing log messages.
+ public ChoicePromptHandler(ILogger logger) : base(logger)
+ {
+ }
+
#region Properties
///
diff --git a/src/PowerShellEditorServices/Console/ConsoleChoicePromptHandler.cs b/src/PowerShellEditorServices/Console/ConsoleChoicePromptHandler.cs
index 3d740cb86..347b6232b 100644
--- a/src/PowerShellEditorServices/Console/ConsoleChoicePromptHandler.cs
+++ b/src/PowerShellEditorServices/Console/ConsoleChoicePromptHandler.cs
@@ -6,6 +6,7 @@
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
+using Microsoft.PowerShell.EditorServices.Utility;
namespace Microsoft.PowerShell.EditorServices.Console
{
@@ -30,7 +31,9 @@ public class ConsoleChoicePromptHandler : ChoicePromptHandler
/// The IConsoleHost implementation to use for writing to the
/// console.
///
- public ConsoleChoicePromptHandler(IConsoleHost consoleHost)
+ /// An ILogger implementation used for writing log messages.
+ public ConsoleChoicePromptHandler(IConsoleHost consoleHost, ILogger logger)
+ : base(logger)
{
this.consoleHost = consoleHost;
}
diff --git a/src/PowerShellEditorServices/Console/ConsoleInputPromptHandler.cs b/src/PowerShellEditorServices/Console/ConsoleInputPromptHandler.cs
index 15d3120e7..672c227a5 100644
--- a/src/PowerShellEditorServices/Console/ConsoleInputPromptHandler.cs
+++ b/src/PowerShellEditorServices/Console/ConsoleInputPromptHandler.cs
@@ -7,6 +7,7 @@
using System.Security;
using System.Threading;
using System.Threading.Tasks;
+using Microsoft.PowerShell.EditorServices.Utility;
namespace Microsoft.PowerShell.EditorServices.Console
{
@@ -31,7 +32,9 @@ public class ConsoleInputPromptHandler : InputPromptHandler
/// The IConsoleHost implementation to use for writing to the
/// console.
///
- public ConsoleInputPromptHandler(IConsoleHost consoleHost)
+ /// An ILogger implementation used for writing log messages.
+ public ConsoleInputPromptHandler(IConsoleHost consoleHost, ILogger logger)
+ : base(logger)
{
this.consoleHost = consoleHost;
}
diff --git a/src/PowerShellEditorServices/Console/ConsolePromptHandlerContext.cs b/src/PowerShellEditorServices/Console/ConsolePromptHandlerContext.cs
index 4b18f3fb3..f1c1a4808 100644
--- a/src/PowerShellEditorServices/Console/ConsolePromptHandlerContext.cs
+++ b/src/PowerShellEditorServices/Console/ConsolePromptHandlerContext.cs
@@ -4,6 +4,7 @@
//
using System;
+using Microsoft.PowerShell.EditorServices.Utility;
namespace Microsoft.PowerShell.EditorServices.Console
{
@@ -15,6 +16,7 @@ public class ConsolePromptHandlerContext : IPromptHandlerContext
{
#region Private Fields
+ private ILogger logger;
private IConsoleHost consoleHost;
#endregion
@@ -29,9 +31,13 @@ public class ConsolePromptHandlerContext : IPromptHandlerContext
/// The IConsoleHost implementation to use for writing to the
/// console.
///
- public ConsolePromptHandlerContext(IConsoleHost consoleHost)
+ /// An ILogger implementation used for writing log messages.
+ public ConsolePromptHandlerContext(
+ IConsoleHost consoleHost,
+ ILogger logger)
{
this.consoleHost = consoleHost;
+ this.logger = logger;
}
#endregion
@@ -47,7 +53,7 @@ public ConsolePromptHandlerContext(IConsoleHost consoleHost)
///
public ChoicePromptHandler GetChoicePromptHandler()
{
- return new ConsoleChoicePromptHandler(this.consoleHost);
+ return new ConsoleChoicePromptHandler(this.consoleHost, this.logger);
}
///
@@ -59,7 +65,7 @@ public ChoicePromptHandler GetChoicePromptHandler()
///
public InputPromptHandler GetInputPromptHandler()
{
- return new ConsoleInputPromptHandler(this.consoleHost);
+ return new ConsoleInputPromptHandler(this.consoleHost, this.logger);
}
#endregion
diff --git a/src/PowerShellEditorServices/Console/ConsoleService.cs b/src/PowerShellEditorServices/Console/ConsoleService.cs
index 06f5df236..60184f93b 100644
--- a/src/PowerShellEditorServices/Console/ConsoleService.cs
+++ b/src/PowerShellEditorServices/Console/ConsoleService.cs
@@ -87,7 +87,7 @@ public ConsoleService(
if (defaultPromptHandlerContext == null)
{
defaultPromptHandlerContext =
- new ConsolePromptHandlerContext(this);
+ new ConsolePromptHandlerContext(this, Logger.CurrentLogger);
}
this.promptHandlerContextStack.Push(
@@ -288,7 +288,7 @@ private void InnerStartReadLoop()
}
else
{
- Logger.Write(LogLevel.Verbose, "InnerStartReadLoop called while read loop is already running");
+ Logger.CurrentLogger.Write(LogLevel.Verbose, "InnerStartReadLoop called while read loop is already running");
}
}
}
@@ -339,7 +339,7 @@ await this.consoleReadLine.ReadCommandLine(
true,
OutputType.Error);
- Logger.WriteException("Caught exception while reading command line", e);
+ Logger.CurrentLogger.WriteException("Caught exception while reading command line", e);
}
if (commandString != null)
@@ -434,7 +434,7 @@ private TPromptHandler GetPromptHandler(
{
if (this.activePromptHandler != null)
{
- Logger.Write(
+ Logger.CurrentLogger.Write(
LogLevel.Error,
"Prompt handler requested while another prompt is already active.");
}
diff --git a/src/PowerShellEditorServices/Console/FieldDetails.cs b/src/PowerShellEditorServices/Console/FieldDetails.cs
index 9a7dc0de3..ffec536b3 100644
--- a/src/PowerShellEditorServices/Console/FieldDetails.cs
+++ b/src/PowerShellEditorServices/Console/FieldDetails.cs
@@ -120,7 +120,7 @@ public virtual void SetValue(object fieldValue, bool hasValue)
/// complete.
///
/// The field's final value.
- public object GetValue()
+ public object GetValue(ILogger logger)
{
object fieldValue = this.OnGetValue();
@@ -133,7 +133,7 @@ public object GetValue()
else
{
// This "shoudln't" happen, so log in case it does
- Logger.Write(
+ logger.Write(
LogLevel.Error,
$"Cannot retrieve value for field {this.Label}");
}
@@ -170,9 +170,14 @@ public virtual FieldDetails GetNextField()
#region Internal Methods
- internal static FieldDetails Create(FieldDescription fieldDescription)
+ internal static FieldDetails Create(
+ FieldDescription fieldDescription,
+ ILogger logger)
{
- Type fieldType = GetFieldTypeFromTypeName(fieldDescription.ParameterAssemblyFullName);
+ Type fieldType =
+ GetFieldTypeFromTypeName(
+ fieldDescription.ParameterAssemblyFullName,
+ logger);
if (typeof(IList).GetTypeInfo().IsAssignableFrom(fieldType.GetTypeInfo()))
{
@@ -203,15 +208,17 @@ internal static FieldDetails Create(FieldDescription fieldDescription)
}
}
- private static Type GetFieldTypeFromTypeName(string assemblyFullName)
+ private static Type GetFieldTypeFromTypeName(
+ string assemblyFullName,
+ ILogger logger)
{
- Type fieldType = typeof(string);
+ Type fieldType = typeof(string);
if (!string.IsNullOrEmpty(assemblyFullName))
{
if (!LanguagePrimitives.TryConvertTo(assemblyFullName, out fieldType))
{
- Logger.Write(
+ logger.Write(
LogLevel.Warning,
string.Format(
"Could not resolve type of field: {0}",
diff --git a/src/PowerShellEditorServices/Console/InputPromptHandler.cs b/src/PowerShellEditorServices/Console/InputPromptHandler.cs
index d59860e1a..5acade505 100644
--- a/src/PowerShellEditorServices/Console/InputPromptHandler.cs
+++ b/src/PowerShellEditorServices/Console/InputPromptHandler.cs
@@ -10,6 +10,7 @@
using System.Security;
using System.Threading;
using System.Threading.Tasks;
+using Microsoft.PowerShell.EditorServices.Utility;
namespace Microsoft.PowerShell.EditorServices.Console
{
@@ -31,6 +32,14 @@ public abstract class InputPromptHandler : PromptHandler
#endregion
+ ///
+ ///
+ ///
+ /// An ILogger implementation used for writing log messages.
+ public InputPromptHandler(ILogger logger) : base(logger)
+ {
+ }
+
#region Properties
///
@@ -312,7 +321,7 @@ private Dictionary GetFieldValues()
foreach (FieldDetails field in this.Fields)
{
- fieldValues.Add(field.OriginalName, field.GetValue());
+ fieldValues.Add(field.OriginalName, field.GetValue(this.Logger));
}
return fieldValues;
@@ -321,4 +330,3 @@ private Dictionary GetFieldValues()
#endregion
}
}
-
diff --git a/src/PowerShellEditorServices/Console/PromptHandler.cs b/src/PowerShellEditorServices/Console/PromptHandler.cs
index a0971561f..e32928fae 100644
--- a/src/PowerShellEditorServices/Console/PromptHandler.cs
+++ b/src/PowerShellEditorServices/Console/PromptHandler.cs
@@ -4,6 +4,7 @@
//
using System;
+using Microsoft.PowerShell.EditorServices.Utility;
namespace Microsoft.PowerShell.EditorServices.Console
{
@@ -12,6 +13,20 @@ namespace Microsoft.PowerShell.EditorServices.Console
///
public abstract class PromptHandler
{
+ ///
+ /// Gets the ILogger used for this instance.
+ ///
+ protected ILogger Logger { get; private set; }
+
+ ///
+ ///
+ ///
+ /// An ILogger implementation used for writing log messages.
+ public PromptHandler(ILogger logger)
+ {
+ this.Logger = logger;
+ }
+
///
/// Called when the active prompt should be cancelled.
///
diff --git a/src/PowerShellEditorServices/Debugging/DebugService.cs b/src/PowerShellEditorServices/Debugging/DebugService.cs
index 6d4c92510..0953e239c 100644
--- a/src/PowerShellEditorServices/Debugging/DebugService.cs
+++ b/src/PowerShellEditorServices/Debugging/DebugService.cs
@@ -29,6 +29,7 @@ public class DebugService
private const string PsesGlobalVariableNamePrefix = "__psEditorServices_";
private const string TemporaryScriptFileName = "Script Listing.ps1";
+ private ILogger logger;
private PowerShellContext powerShellContext;
private RemoteFileManager remoteFileManager;
@@ -79,8 +80,9 @@ public class DebugService
///
/// The PowerShellContext to use for all debugging operations.
///
- public DebugService(PowerShellContext powerShellContext)
- : this(powerShellContext, null)
+ /// An ILogger implementation used for writing log messages.
+ public DebugService(PowerShellContext powerShellContext, ILogger logger)
+ : this(powerShellContext, null, logger)
{
}
@@ -94,12 +96,15 @@ public DebugService(PowerShellContext powerShellContext)
///
/// A RemoteFileManager instance to use for accessing files in remote sessions.
///
+ /// An ILogger implementation used for writing log messages.
public DebugService(
PowerShellContext powerShellContext,
- RemoteFileManager remoteFileManager)
+ RemoteFileManager remoteFileManager,
+ ILogger logger)
{
Validate.IsNotNull(nameof(powerShellContext), powerShellContext);
+ this.logger = logger;
this.powerShellContext = powerShellContext;
this.powerShellContext.DebuggerStop += this.OnDebuggerStop;
this.powerShellContext.DebuggerResumed += this.OnDebuggerResumed;
@@ -145,7 +150,7 @@ public async Task SetLineBreakpoints(
{
if (!this.remoteFileManager.IsUnderRemoteTempPath(scriptPath))
{
- Logger.Write(
+ this.logger.Write(
LogLevel.Verbose,
$"Could not set breakpoints for local path '{scriptPath}' in a remote session.");
@@ -163,7 +168,7 @@ public async Task SetLineBreakpoints(
this.temporaryScriptListingPath != null &&
this.temporaryScriptListingPath.Equals(scriptPath, StringComparison.CurrentCultureIgnoreCase))
{
- Logger.Write(
+ this.logger.Write(
LogLevel.Verbose,
$"Could not set breakpoint on temporary script listing path '{scriptPath}'.");
@@ -361,7 +366,7 @@ public VariableDetailsBase[] GetVariables(int variableReferenceId)
VariableDetailsBase parentVariable = this.variables[variableReferenceId];
if (parentVariable.IsExpandable)
{
- childVariables = parentVariable.GetChildren();
+ childVariables = parentVariable.GetChildren(this.logger);
foreach (var child in childVariables)
{
// Only add child if it hasn't already been added.
@@ -439,7 +444,7 @@ public async Task SetVariable(int variableContainerReferenceId, string n
Validate.IsNotNull(nameof(name), name);
Validate.IsNotNull(nameof(value), value);
- Logger.Write(LogLevel.Verbose, $"SetVariableRequest for '{name}' to value string (pre-quote processing): '{value}'");
+ this.logger.Write(LogLevel.Verbose, $"SetVariableRequest for '{name}' to value string (pre-quote processing): '{value}'");
// An empty or whitespace only value is not a valid expression for SetVariable.
if (value.Trim().Length == 0)
@@ -552,7 +557,7 @@ await this.powerShellContext.ExecuteCommand
///
- public override VariableDetailsBase[] GetChildren()
+ public override VariableDetailsBase[] GetChildren(ILogger logger)
{
var variablesArray = new VariableDetailsBase[this.children.Count];
this.children.Values.CopyTo(variablesArray, 0);
diff --git a/src/PowerShellEditorServices/Debugging/VariableDetails.cs b/src/PowerShellEditorServices/Debugging/VariableDetails.cs
index a4a3014f7..342f045a5 100644
--- a/src/PowerShellEditorServices/Debugging/VariableDetails.cs
+++ b/src/PowerShellEditorServices/Debugging/VariableDetails.cs
@@ -15,7 +15,7 @@
namespace Microsoft.PowerShell.EditorServices
{
///
- /// Contains details pertaining to a variable in the current
+ /// Contains details pertaining to a variable in the current
/// debugging session.
///
[DebuggerDisplay("Name = {Name}, Id = {Id}, Value = {ValueString}")]
@@ -99,7 +99,7 @@ public VariableDetails(string name, object value)
/// details of its children. Otherwise it returns an empty array.
///
///
- public override VariableDetailsBase[] GetChildren()
+ public override VariableDetailsBase[] GetChildren(ILogger logger)
{
VariableDetails[] childVariables = null;
@@ -107,7 +107,7 @@ public override VariableDetailsBase[] GetChildren()
{
if (this.cachedChildren == null)
{
- this.cachedChildren = GetChildren(this.valueObject);
+ this.cachedChildren = GetChildren(this.valueObject, logger);
}
return this.cachedChildren;
@@ -126,7 +126,7 @@ public override VariableDetailsBase[] GetChildren()
private static bool GetIsExpandable(object valueObject)
{
- if (valueObject == null)
+ if (valueObject == null)
{
return false;
}
@@ -138,9 +138,9 @@ private static bool GetIsExpandable(object valueObject)
valueObject = psobject.BaseObject;
}
- Type valueType =
- valueObject != null ?
- valueObject.GetType() :
+ Type valueType =
+ valueObject != null ?
+ valueObject.GetType() :
null;
TypeInfo valueTypeInfo = valueType.GetTypeInfo();
@@ -172,7 +172,7 @@ private static string GetValueString(object value, bool isExpandable)
{
Type objType = value.GetType();
- // Get the "value" for an expandable object.
+ // Get the "value" for an expandable object.
if (value is DictionaryEntry)
{
// For DictionaryEntry - display the key/value as the value.
@@ -189,7 +189,7 @@ private static string GetValueString(object value, bool isExpandable)
if (valueToString.Equals(objType.ToString()))
{
- // If the ToString() matches the type name, then display the type
+ // If the ToString() matches the type name, then display the type
// name in PowerShell format.
string shortTypeName = objType.Name;
@@ -254,7 +254,7 @@ private static string InsertDimensionSize(string value, int dimensionSize)
return result;
}
- private VariableDetails[] GetChildren(object obj)
+ private VariableDetails[] GetChildren(object obj, ILogger logger)
{
List childVariables = new List();
@@ -267,7 +267,7 @@ private VariableDetails[] GetChildren(object obj)
{
PSObject psObject = obj as PSObject;
- if ((psObject != null) &&
+ if ((psObject != null) &&
(psObject.TypeNames[0] == typeof(PSCustomObject).ToString()))
{
// PowerShell PSCustomObject's properties are completely defined by the ETS type system.
@@ -276,7 +276,7 @@ private VariableDetails[] GetChildren(object obj)
.Properties
.Select(p => new VariableDetails(p)));
}
- else
+ else
{
// If a PSObject other than a PSCustomObject, unwrap it.
if (psObject != null)
@@ -296,21 +296,21 @@ private VariableDetails[] GetChildren(object obj)
// We're in the realm of regular, unwrapped .NET objects
if (dictionary != null)
- {
+ {
// Buckle up kids, this is a bit weird. We could not use the LINQ
// operator OfType. Even though R# will squiggle the
// "foreach" keyword below and offer to convert to a LINQ-expression - DON'T DO IT!
// The reason is that LINQ extension methods work with objects of type
// IEnumerable. Objects of type Dictionary<,>, respond to iteration via
- // IEnumerable by returning KeyValuePair<,> objects. Unfortunately non-generic
+ // IEnumerable by returning KeyValuePair<,> objects. Unfortunately non-generic
// dictionaries like HashTable return DictionaryEntry objects.
// It turns out that iteration via C#'s foreach loop, operates on the variable's
// type which in this case is IDictionary. IDictionary was designed to always
// return DictionaryEntry objects upon iteration and the Dictionary<,> implementation
// honors that when the object is reintepreted as an IDictionary object.
// FYI, a test case for this is to open $PSBoundParameters when debugging a
- // function that defines parameters and has been passed parameters.
- // If you open the $PSBoundParameters variable node in this scenario and see nothing,
+ // function that defines parameters and has been passed parameters.
+ // If you open the $PSBoundParameters variable node in this scenario and see nothing,
// this code is broken.
int i = 0;
foreach (DictionaryEntry entry in dictionary)
@@ -343,7 +343,7 @@ private VariableDetails[] GetChildren(object obj)
// we aren't loading children on the pipeline thread so
// this causes an exception to be raised. In this case,
// just return an empty list of children.
- Logger.Write(LogLevel.Warning, $"Failed to get properties of variable {this.Name}, value invocation was attempted: {ex.Message}");
+ logger.Write(LogLevel.Warning, $"Failed to get properties of variable {this.Name}, value invocation was attempted: {ex.Message}");
}
return childVariables.ToArray();
diff --git a/src/PowerShellEditorServices/Debugging/VariableDetailsBase.cs b/src/PowerShellEditorServices/Debugging/VariableDetailsBase.cs
index 11d466750..eb1f27c8f 100644
--- a/src/PowerShellEditorServices/Debugging/VariableDetailsBase.cs
+++ b/src/PowerShellEditorServices/Debugging/VariableDetailsBase.cs
@@ -3,10 +3,12 @@
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
//
+using Microsoft.PowerShell.EditorServices.Utility;
+
namespace Microsoft.PowerShell.EditorServices
{
///
- /// Defines the common details between a variable and a variable container such as a scope
+ /// Defines the common details between a variable and a variable container such as a scope
/// in the current debugging session.
///
public abstract class VariableDetailsBase
@@ -47,6 +49,6 @@ public abstract class VariableDetailsBase
/// details of its children. Otherwise it returns an empty array.
///
///
- public abstract VariableDetailsBase[] GetChildren();
+ public abstract VariableDetailsBase[] GetChildren(ILogger logger);
}
-}
\ No newline at end of file
+}
diff --git a/src/PowerShellEditorServices/Language/AstOperations.cs b/src/PowerShellEditorServices/Language/AstOperations.cs
index da45431bd..36a79a298 100644
--- a/src/PowerShellEditorServices/Language/AstOperations.cs
+++ b/src/PowerShellEditorServices/Language/AstOperations.cs
@@ -39,6 +39,7 @@ internal static class AstOperations
///
/// The PowerShellContext to use for gathering completions.
///
+ /// An ILogger implementation used for writing log messages.
///
/// A CancellationToken to cancel completion requests.
///
@@ -51,6 +52,7 @@ static public async Task GetCompletions(
Token[] currentTokens,
int fileOffset,
PowerShellContext powerShellContext,
+ ILogger logger,
CancellationToken cancellationToken)
{
var type = scriptAst.Extent.StartScriptPosition.GetType();
@@ -72,7 +74,7 @@ static public async Task GetCompletions(
scriptAst.Extent.StartScriptPosition,
new object[] { fileOffset });
- Logger.Write(
+ logger.Write(
LogLevel.Verbose,
string.Format(
"Getting completions at offset {0} (line: {1}, column: {2})",
@@ -99,7 +101,7 @@ static public async Task GetCompletions(
ErrorRecord errorRecord = outputObject.BaseObject as ErrorRecord;
if (errorRecord != null)
{
- Logger.WriteException(
+ logger.WriteException(
"Encountered an error while invoking TabExpansion2 in the debugger",
errorRecord.Exception);
}
@@ -130,7 +132,7 @@ static public async Task GetCompletions(
stopwatch.Stop();
- Logger.Write(LogLevel.Verbose, $"IntelliSense completed in {stopwatch.ElapsedMilliseconds}ms.");
+ logger.Write(LogLevel.Verbose, $"IntelliSense completed in {stopwatch.ElapsedMilliseconds}ms.");
}
}
diff --git a/src/PowerShellEditorServices/Language/LanguageService.cs b/src/PowerShellEditorServices/Language/LanguageService.cs
index f808a2a1d..b0a375cce 100644
--- a/src/PowerShellEditorServices/Language/LanguageService.cs
+++ b/src/PowerShellEditorServices/Language/LanguageService.cs
@@ -24,6 +24,7 @@ public class LanguageService
{
#region Private Fields
+ private ILogger logger;
private bool areAliasesLoaded;
private PowerShellContext powerShellContext;
private CompletionResults mostRecentCompletions;
@@ -46,11 +47,15 @@ public class LanguageService
///
/// The PowerShellContext in which language service operations will be executed.
///
- public LanguageService(PowerShellContext powerShellContext)
+ /// An ILogger implementation used for writing log messages.
+ public LanguageService(
+ PowerShellContext powerShellContext,
+ ILogger logger)
{
Validate.IsNotNull("powerShellContext", powerShellContext);
this.powerShellContext = powerShellContext;
+ this.logger = logger;
this.CmdletToAliasDictionary = new Dictionary>(StringComparer.OrdinalIgnoreCase);
this.AliasToCmdletDictionary = new Dictionary(StringComparer.OrdinalIgnoreCase);
@@ -96,6 +101,7 @@ await AstOperations.GetCompletions(
scriptFile.ScriptTokens,
fileOffset,
this.powerShellContext,
+ this.logger,
new CancellationTokenSource(DefaultWaitTimeoutMilliseconds).Token);
if (commandCompletion != null)
@@ -119,7 +125,7 @@ await AstOperations.GetCompletions(
{
// Bad completion results could return an invalid
// replacement range, catch that here
- Logger.Write(
+ this.logger.Write(
LogLevel.Error,
$"Caught exception while trying to create CompletionResults:\n\n{e.ToString()}");
}
@@ -486,7 +492,7 @@ await CommandHelpers.GetCommandInfo(
// A RuntimeException will be thrown when an invalid attribute is
// on a parameter binding block and then that command/script has
// its signatures resolved by typing it into a script.
- Logger.WriteException("RuntimeException encountered while accessing command parameter sets", e);
+ this.logger.WriteException("RuntimeException encountered while accessing command parameter sets", e);
return null;
}
diff --git a/src/PowerShellEditorServices/Session/Capabilities/DscBreakpointCapability.cs b/src/PowerShellEditorServices/Session/Capabilities/DscBreakpointCapability.cs
index 175030565..bdbcb6f7b 100644
--- a/src/PowerShellEditorServices/Session/Capabilities/DscBreakpointCapability.cs
+++ b/src/PowerShellEditorServices/Session/Capabilities/DscBreakpointCapability.cs
@@ -79,7 +79,8 @@ public bool IsDscResourcePath(string scriptPath)
public static DscBreakpointCapability CheckForCapability(
RunspaceDetails runspaceDetails,
- PowerShellContext powerShellContext)
+ PowerShellContext powerShellContext,
+ ILogger logger)
{
DscBreakpointCapability capability = null;
@@ -103,12 +104,12 @@ public static DscBreakpointCapability CheckForCapability(
}
catch (CmdletInvocationException e)
{
- Logger.WriteException("Could not load the DSC module!", e);
+ logger.WriteException("Could not load the DSC module!", e);
}
if (moduleInfo != null)
{
- Logger.Write(LogLevel.Verbose, "Side-by-side DSC module found, gathering DSC resource paths...");
+ logger.Write(LogLevel.Verbose, "Side-by-side DSC module found, gathering DSC resource paths...");
// The module was loaded, add the breakpoint capability
capability = new DscBreakpointCapability();
@@ -132,7 +133,7 @@ public static DscBreakpointCapability CheckForCapability(
}
catch (CmdletInvocationException e)
{
- Logger.WriteException("Get-DscResource failed!", e);
+ logger.WriteException("Get-DscResource failed!", e);
}
if (resourcePaths != null)
@@ -142,16 +143,16 @@ public static DscBreakpointCapability CheckForCapability(
.Select(o => (string)o.BaseObject)
.ToArray();
- Logger.Write(LogLevel.Verbose, $"DSC resources found: {resourcePaths.Count}");
+ logger.Write(LogLevel.Verbose, $"DSC resources found: {resourcePaths.Count}");
}
else
{
- Logger.Write(LogLevel.Verbose, $"No DSC resources found.");
+ logger.Write(LogLevel.Verbose, $"No DSC resources found.");
}
}
else
{
- Logger.Write(LogLevel.Verbose, $"Side-by-side DSC module was not found.");
+ logger.Write(LogLevel.Verbose, $"Side-by-side DSC module was not found.");
}
}
}
diff --git a/src/PowerShellEditorServices/Session/EditorSession.cs b/src/PowerShellEditorServices/Session/EditorSession.cs
index f1f16365b..e72e26588 100644
--- a/src/PowerShellEditorServices/Session/EditorSession.cs
+++ b/src/PowerShellEditorServices/Session/EditorSession.cs
@@ -18,6 +18,12 @@ namespace Microsoft.PowerShell.EditorServices
///
public class EditorSession
{
+ #region Private Fields
+
+ private ILogger logger;
+
+ #endregion
+
#region Properties
///
@@ -73,6 +79,19 @@ public class EditorSession
#endregion
+ #region Constructors
+
+ ///
+ ///
+ ///
+ /// An ILogger implementation used for writing log messages.
+ public EditorSession(ILogger logger)
+ {
+ this.logger = logger;
+ }
+
+ #endregion
+
#region Public Methods
///
@@ -90,14 +109,14 @@ public void StartSession(
this.ConsoleService = consoleService;
this.UsesConsoleHost = this.ConsoleService.EnableConsoleRepl;
- this.LanguageService = new LanguageService(this.PowerShellContext);
+ this.LanguageService = new LanguageService(this.PowerShellContext, this.logger);
this.ExtensionService = new ExtensionService(this.PowerShellContext);
- this.TemplateService = new TemplateService(this.PowerShellContext);
+ this.TemplateService = new TemplateService(this.PowerShellContext, this.logger);
this.InstantiateAnalysisService();
// Create a workspace to contain open files
- this.Workspace = new Workspace(this.PowerShellContext.LocalPowerShellVersion.Version);
+ this.Workspace = new Workspace(this.PowerShellContext.LocalPowerShellVersion.Version, this.logger);
}
///
@@ -118,11 +137,11 @@ public void StartDebugSession(
this.PowerShellContext = powerShellContext;
this.ConsoleService = consoleService;
- this.RemoteFileManager = new RemoteFileManager(this.PowerShellContext, editorOperations);
- this.DebugService = new DebugService(this.PowerShellContext, this.RemoteFileManager);
+ this.RemoteFileManager = new RemoteFileManager(this.PowerShellContext, editorOperations, logger);
+ this.DebugService = new DebugService(this.PowerShellContext, this.RemoteFileManager, logger);
// Create a workspace to contain open files
- this.Workspace = new Workspace(this.PowerShellContext.LocalPowerShellVersion.Version);
+ this.Workspace = new Workspace(this.PowerShellContext.LocalPowerShellVersion.Version, this.logger);
}
///
@@ -135,8 +154,8 @@ public void StartDebugService(IEditorOperations editorOperations)
{
if (this.DebugService == null)
{
- this.RemoteFileManager = new RemoteFileManager(this.PowerShellContext, editorOperations);
- this.DebugService = new DebugService(this.PowerShellContext, this.RemoteFileManager);
+ this.RemoteFileManager = new RemoteFileManager(this.PowerShellContext, editorOperations, logger);
+ this.DebugService = new DebugService(this.PowerShellContext, this.RemoteFileManager, logger);
}
}
@@ -146,11 +165,11 @@ internal void InstantiateAnalysisService(string settingsPath = null)
// Script Analyzer binaries are not included.
try
{
- this.AnalysisService = new AnalysisService(settingsPath);
+ this.AnalysisService = new AnalysisService(settingsPath, this.logger);
}
catch (FileNotFoundException)
{
- Logger.Write(
+ this.logger.Write(
LogLevel.Warning,
"Script Analyzer binaries not found, AnalysisService will be disabled.");
}
diff --git a/src/PowerShellEditorServices/Session/PowerShellContext.cs b/src/PowerShellEditorServices/Session/PowerShellContext.cs
index 7a87c2363..a0c962b80 100644
--- a/src/PowerShellEditorServices/Session/PowerShellContext.cs
+++ b/src/PowerShellEditorServices/Session/PowerShellContext.cs
@@ -33,6 +33,7 @@ public class PowerShellContext : IDisposable, IHostSupportsInteractiveSession
{
#region Fields
+ private ILogger logger;
private PowerShell powerShell;
private bool ownsInitialRunspace;
private RunspaceDetails initialRunspace;
@@ -106,6 +107,15 @@ public RunspaceDetails CurrentRunspace
#region Constructors
+ ///
+ ///
+ ///
+ /// An ILogger implementation used for writing log messages.
+ public PowerShellContext(ILogger logger)
+ {
+ this.logger = logger;
+ }
+
///
///
///
@@ -180,7 +190,8 @@ public void Initialize(
// Get the PowerShell runtime version
this.LocalPowerShellVersion =
PowerShellVersionDetails.GetVersionDetails(
- initialRunspace);
+ initialRunspace,
+ this.logger);
this.powerShell = PowerShell.Create();
this.powerShell.Runspace = initialRunspace;
@@ -196,7 +207,7 @@ public void Initialize(
this.CurrentRunspace = this.initialRunspace;
// Write out the PowerShell version for tracking purposes
- Logger.Write(
+ this.logger.Write(
LogLevel.Normal,
string.Format(
"PowerShell runtime version: {0}, edition: {1}",
@@ -422,7 +433,7 @@ public async Task> ExecuteCommand(
if (Thread.CurrentThread.ManagedThreadId != this.pipelineThreadId &&
this.pipelineExecutionTask != null)
{
- Logger.Write(LogLevel.Verbose, "Passing command execution to pipeline thread.");
+ this.logger.Write(LogLevel.Verbose, "Passing command execution to pipeline thread.");
PipelineExecutionRequest executionRequest =
new PipelineExecutionRequest(
@@ -467,7 +478,7 @@ public async Task> ExecuteCommand(
}
else
{
- Logger.Write(
+ this.logger.Write(
LogLevel.Verbose,
string.Format(
"Attempting to execute command(s):\r\n\r\n{0}",
@@ -521,13 +532,13 @@ await Task.Factory.StartNew>(
}
errorMessages?.Append(errorMessage);
- Logger.Write(LogLevel.Error, errorMessage);
+ this.logger.Write(LogLevel.Error, errorMessage);
hadErrors = true;
}
else
{
- Logger.Write(
+ this.logger.Write(
LogLevel.Verbose,
"Execution completed successfully.");
}
@@ -535,7 +546,7 @@ await Task.Factory.StartNew>(
}
catch (PipelineStoppedException e)
{
- Logger.Write(
+ this.logger.Write(
LogLevel.Error,
"Pipeline stopped while executing command:\r\n\r\n" + e.ToString());
@@ -543,7 +554,7 @@ await Task.Factory.StartNew>(
}
catch (RuntimeException e)
{
- Logger.Write(
+ this.logger.Write(
LogLevel.Error,
"Runtime exception occurred while executing command:\r\n\r\n" + e.ToString());
@@ -744,7 +755,7 @@ public async Task ExecuteScriptWithArgs(string script, string arguments = null,
}
catch (System.Management.Automation.DriveNotFoundException e)
{
- Logger.Write(
+ this.logger.Write(
LogLevel.Error,
"Could not determine current filesystem location:\r\n\r\n" + e.ToString());
}
@@ -858,7 +869,7 @@ public void AbortExecution()
if (this.SessionState != PowerShellContextState.Aborting &&
this.SessionState != PowerShellContextState.Disposed)
{
- Logger.Write(LogLevel.Verbose, "Execution abort requested...");
+ this.logger.Write(LogLevel.Verbose, "Execution abort requested...");
// Clean up the debugger
if (this.IsDebuggerStopped)
@@ -880,7 +891,7 @@ public void AbortExecution()
}
else
{
- Logger.Write(
+ this.logger.Write(
LogLevel.Verbose,
string.Format(
$"Execution abort requested when already aborted (SessionState = {this.SessionState})"));
@@ -894,7 +905,7 @@ public void AbortExecution()
///
internal void BreakExecution()
{
- Logger.Write(LogLevel.Verbose, "Debugger break requested...");
+ this.logger.Write(LogLevel.Verbose, "Debugger break requested...");
// Pause the debugger
this.versionSpecificOperations.PauseDebugger(
@@ -909,14 +920,14 @@ internal void ResumeDebugger(DebuggerResumeAction resumeAction)
// The execution thread will clean up the task.
if (!this.debuggerStoppedTask.TrySetResult(resumeAction))
{
- Logger.Write(
+ this.logger.Write(
LogLevel.Error,
$"Tried to resume debugger with action {resumeAction} but the task was already completed.");
}
}
else
{
- Logger.Write(
+ this.logger.Write(
LogLevel.Error,
$"Tried to resume debugger with action {resumeAction} but there was no debuggerStoppedTask.");
}
@@ -1025,7 +1036,7 @@ private void CloseRunspace(RunspaceDetails runspaceDetails)
if (exitException != null)
{
- Logger.Write(
+ this.logger.Write(
LogLevel.Error,
$"Caught {exitException.GetType().Name} while exiting {runspaceDetails.Location} runspace:\r\n{exitException.ToString()}");
}
@@ -1044,7 +1055,7 @@ internal void ReleaseRunspaceHandle(RunspaceHandle runspaceHandle)
else
{
// Write the situation to the log since this shouldn't happen
- Logger.Write(
+ this.logger.Write(
LogLevel.Error,
"The PowerShellContext.runspaceWaitQueue has more than one item");
}
@@ -1111,7 +1122,7 @@ private void OnSessionStateChanged(object sender, SessionStateChangedEventArgs e
{
if (this.SessionState != PowerShellContextState.Disposed)
{
- Logger.Write(
+ this.logger.Write(
LogLevel.Verbose,
string.Format(
"Session state changed --\r\n\r\n Old state: {0}\r\n New state: {1}\r\n Result: {2}",
@@ -1124,7 +1135,7 @@ private void OnSessionStateChanged(object sender, SessionStateChangedEventArgs e
}
else
{
- Logger.Write(
+ this.logger.Write(
LogLevel.Warning,
$"Received session state change to {e.NewSessionState} when already disposed");
}
@@ -1164,7 +1175,7 @@ private void OnExecutionStatusChanged(
private IEnumerable ExecuteCommandInDebugger(PSCommand psCommand, bool sendOutputToHost)
{
- Logger.Write(
+ this.logger.Write(
LogLevel.Verbose,
string.Format(
"Attempting to execute command(s) in the debugger:\r\n\r\n{0}",
@@ -1387,7 +1398,7 @@ private void SetExecutionPolicy(ExecutionPolicy desiredExecutionPolicy)
desiredExecutionPolicy == ExecutionPolicy.Bypass ||
currentPolicy == ExecutionPolicy.Undefined)
{
- Logger.Write(
+ this.logger.Write(
LogLevel.Verbose,
string.Format(
"Setting execution policy:\r\n Current = ExecutionPolicy.{0}\r\n Desired = ExecutionPolicy.{1}",
@@ -1407,7 +1418,7 @@ private void SetExecutionPolicy(ExecutionPolicy desiredExecutionPolicy)
}
catch (CmdletInvocationException e)
{
- Logger.WriteException(
+ this.logger.WriteException(
$"An error occurred while calling Set-ExecutionPolicy, the desired policy of {desiredExecutionPolicy} may not be set.",
e);
}
@@ -1416,7 +1427,7 @@ private void SetExecutionPolicy(ExecutionPolicy desiredExecutionPolicy)
}
else
{
- Logger.Write(
+ this.logger.Write(
LogLevel.Verbose,
string.Format(
"Current execution policy: ExecutionPolicy.{0}",
@@ -1438,7 +1449,7 @@ private SessionDetails GetSessionDetails(Func invokeAction)
}
catch (RuntimeException e)
{
- Logger.Write(
+ this.logger.Write(
LogLevel.Verbose,
"Runtime exception occurred while gathering runspace info:\r\n\r\n" + e.ToString());
}
@@ -1534,7 +1545,7 @@ private void SetProfileVariableInCurrentRunspace(ProfilePaths profilePaths)
nameof(profilePaths.CurrentUserCurrentHost),
profilePaths.CurrentUserCurrentHost));
- Logger.Write(
+ this.logger.Write(
LogLevel.Verbose,
string.Format(
"Setting $profile variable in runspace. Current user host profile path: {0}",
@@ -1584,7 +1595,7 @@ private void HandleRunspaceStateChanged(object sender, RunspaceStateEventArgs ar
private void OnDebuggerStop(object sender, DebuggerStopEventArgs e)
{
- Logger.Write(LogLevel.Verbose, "Debugger stopped execution.");
+ this.logger.Write(LogLevel.Verbose, "Debugger stopped execution.");
// Set the task so a result can be set
this.debuggerStoppedTask =
@@ -1616,7 +1627,7 @@ private void OnDebuggerStop(object sender, DebuggerStopEventArgs e)
// Raise the event for the debugger service
this.DebuggerStop?.Invoke(sender, e);
- Logger.Write(LogLevel.Verbose, "Starting pipeline thread message loop...");
+ this.logger.Write(LogLevel.Verbose, "Starting pipeline thread message loop...");
while (true)
{
@@ -1631,7 +1642,7 @@ private void OnDebuggerStop(object sender, DebuggerStopEventArgs e)
this.WriteOutput("", true);
e.ResumeAction = localDebuggerStoppedTask.Result;
- Logger.Write(LogLevel.Verbose, "Received debugger resume action " + e.ResumeAction.ToString());
+ this.logger.Write(LogLevel.Verbose, "Received debugger resume action " + e.ResumeAction.ToString());
// Notify listeners that the debugger has resumed
this.DebuggerResumed?.Invoke(this, e.ResumeAction);
@@ -1658,7 +1669,7 @@ private void OnDebuggerStop(object sender, DebuggerStopEventArgs e)
}
else if (taskIndex == 1)
{
- Logger.Write(LogLevel.Verbose, "Received pipeline thread execution request.");
+ this.logger.Write(LogLevel.Verbose, "Received pipeline thread execution request.");
IPipelineExecutionRequest executionRequest = localPipelineExecutionTask.Result;
@@ -1667,7 +1678,7 @@ private void OnDebuggerStop(object sender, DebuggerStopEventArgs e)
executionRequest.Execute().Wait();
- Logger.Write(LogLevel.Verbose, "Pipeline thread execution completed.");
+ this.logger.Write(LogLevel.Verbose, "Pipeline thread execution completed.");
if (this.CurrentRunspace.Runspace.RunspaceAvailability == RunspaceAvailability.Available)
{
@@ -1761,12 +1772,12 @@ await this.powerShellContext.ExecuteCommand(
private void ConfigureRunspaceCapabilities(RunspaceDetails runspaceDetails)
{
- DscBreakpointCapability.CheckForCapability(this.CurrentRunspace, this);
+ DscBreakpointCapability.CheckForCapability(this.CurrentRunspace, this, this.logger);
}
private void PushRunspace(RunspaceDetails newRunspaceDetails)
{
- Logger.Write(
+ this.logger.Write(
LogLevel.Verbose,
$"Pushing {this.CurrentRunspace.Location} ({this.CurrentRunspace.Context}), new runspace is {newRunspaceDetails.Location} ({newRunspaceDetails.Context}), connection: {newRunspaceDetails.ConnectionString}");
@@ -1869,7 +1880,7 @@ private void PopRunspace()
RunspaceDetails previousRunspace = this.CurrentRunspace;
this.CurrentRunspace = this.runspaceStack.Pop();
- Logger.Write(
+ this.logger.Write(
LogLevel.Verbose,
$"Popping {previousRunspace.Location} ({previousRunspace.Context}), new runspace is {this.CurrentRunspace.Location} ({this.CurrentRunspace.Context}), connection: {this.CurrentRunspace.ConnectionString}");
@@ -1896,7 +1907,7 @@ private void PopRunspace()
}
else
{
- Logger.Write(
+ this.logger.Write(
LogLevel.Error,
"Caller attempted to pop a runspace when no runspaces are on the stack.");
}
@@ -1931,7 +1942,8 @@ void IHostSupportsInteractiveSession.PushRunspace(Runspace runspace)
this.PushRunspace(
RunspaceDetails.CreateFromRunspace(
runspace,
- sessionDetails));
+ sessionDetails,
+ this.logger));
}
void IHostSupportsInteractiveSession.PopRunspace()
diff --git a/src/PowerShellEditorServices/Session/PowerShellVersionDetails.cs b/src/PowerShellEditorServices/Session/PowerShellVersionDetails.cs
index 8a3a54a4f..efd5e5feb 100644
--- a/src/PowerShellEditorServices/Session/PowerShellVersionDetails.cs
+++ b/src/PowerShellEditorServices/Session/PowerShellVersionDetails.cs
@@ -42,7 +42,7 @@ public class PowerShellVersionDetails
/// Gets the version of the PowerShell runtime.
///
public Version Version { get; private set; }
-
+
///
/// Gets the full version string, either the ToString of the Version
/// property or the GitCommitId for open-source PowerShell releases.
@@ -90,8 +90,9 @@ public PowerShellVersionDetails(
/// Gets the PowerShell version details for the given runspace.
///
/// The runspace for which version details will be gathered.
+ /// An ILogger implementation used for writing log messages.
/// A new PowerShellVersionDetails instance.
- public static PowerShellVersionDetails GetVersionDetails(Runspace runspace)
+ public static PowerShellVersionDetails GetVersionDetails(Runspace runspace, ILogger logger)
{
Version powerShellVersion = new Version(5, 0);
string versionString = null;
@@ -149,7 +150,7 @@ public static PowerShellVersionDetails GetVersionDetails(Runspace runspace)
}
catch (Exception ex)
{
- Logger.Write(
+ logger.Write(
LogLevel.Warning,
"Failed to look up PowerShell version, defaulting to version 5.\r\n\r\n" + ex.ToString());
}
diff --git a/src/PowerShellEditorServices/Session/RemoteFileManager.cs b/src/PowerShellEditorServices/Session/RemoteFileManager.cs
index e43921b26..81e4d8f40 100644
--- a/src/PowerShellEditorServices/Session/RemoteFileManager.cs
+++ b/src/PowerShellEditorServices/Session/RemoteFileManager.cs
@@ -25,6 +25,7 @@ public class RemoteFileManager
{
#region Fields
+ private ILogger logger;
private string remoteFilesPath;
private string processTempPath;
private PowerShellContext powerShellContext;
@@ -100,12 +101,15 @@ public class RemoteFileManager
///
/// The IEditorOperations instance to use for opening/closing files in the editor.
///
+ /// An ILogger implementation used for writing log messages.
public RemoteFileManager(
PowerShellContext powerShellContext,
- IEditorOperations editorOperations)
+ IEditorOperations editorOperations,
+ ILogger logger)
{
Validate.IsNotNull(nameof(powerShellContext), powerShellContext);
+ this.logger = logger;
this.powerShellContext = powerShellContext;
this.powerShellContext.RunspaceChanged += HandleRunspaceChanged;
@@ -176,7 +180,7 @@ public async Task FetchRemoteFile(
}
else
{
- Logger.Write(
+ this.logger.Write(
LogLevel.Warning,
$"Could not load contents of remote file '{remoteFilePath}'");
}
@@ -185,7 +189,7 @@ public async Task FetchRemoteFile(
}
catch (IOException e)
{
- Logger.Write(
+ this.logger.Write(
LogLevel.Error,
$"Caught {e.GetType().Name} while attempting to get remote file at path '{remoteFilePath}'\r\n\r\n{e.ToString()}");
}
@@ -211,7 +215,7 @@ public async Task SaveRemoteFile(string localFilePath)
localFilePath,
this.powerShellContext.CurrentRunspace);
- Logger.Write(
+ this.logger.Write(
LogLevel.Verbose,
$"Saving remote file {remoteFilePath} (local path: {localFilePath})");
@@ -222,7 +226,7 @@ public async Task SaveRemoteFile(string localFilePath)
}
catch (IOException e)
{
- Logger.WriteException(
+ this.logger.WriteException(
"Failed to read contents of local copy of remote file",
e);
@@ -245,7 +249,7 @@ await this.powerShellContext.ExecuteCommand(
if (errorMessages.Length > 0)
{
- Logger.Write(LogLevel.Error, $"Remote file save failed due to an error:\r\n\r\n{errorMessages}");
+ this.logger.Write(LogLevel.Error, $"Remote file save failed due to an error:\r\n\r\n{errorMessages}");
}
}
@@ -276,7 +280,7 @@ public string CreateTemporaryFile(string fileName, string fileContents, Runspace
}
catch (IOException e)
{
- Logger.Write(
+ this.logger.Write(
LogLevel.Error,
$"Caught {e.GetType().Name} while attempting to write temporary file at path '{temporaryFilePath}'\r\n\r\n{e.ToString()}");
@@ -432,7 +436,7 @@ private void HandlePSEventReceived(object sender, PSEventArgs args)
}
catch (NullReferenceException e)
{
- Logger.WriteException("Could not store null remote file content", e);
+ this.logger.WriteException("Could not store null remote file content", e);
}
}
}
@@ -474,7 +478,7 @@ private void RegisterPSEditFunction(RunspaceDetails runspaceDetails)
}
catch (RemoteException e)
{
- Logger.WriteException("Could not create psedit function.", e);
+ this.logger.WriteException("Could not create psedit function.", e);
}
}
}
@@ -503,7 +507,7 @@ private void RemovePSEditFunction(RunspaceDetails runspaceDetails)
}
catch (Exception e) when (e is RemoteException || e is PSInvalidOperationException)
{
- Logger.WriteException("Could not remove psedit function.", e);
+ this.logger.WriteException("Could not remove psedit function.", e);
}
}
}
@@ -521,7 +525,7 @@ private void TryDeleteTemporaryPath()
}
catch (IOException e)
{
- Logger.WriteException(
+ this.logger.WriteException(
$"Could not delete temporary folder for current process: {this.processTempPath}", e);
}
}
diff --git a/src/PowerShellEditorServices/Session/RunspaceDetails.cs b/src/PowerShellEditorServices/Session/RunspaceDetails.cs
index 7a399db1e..072129598 100644
--- a/src/PowerShellEditorServices/Session/RunspaceDetails.cs
+++ b/src/PowerShellEditorServices/Session/RunspaceDetails.cs
@@ -183,10 +183,12 @@ internal bool HasCapability()
///
/// The SessionDetails for the runspace.
///
+ /// An ILogger implementation used for writing log messages.
/// A new RunspaceDetails instance.
internal static RunspaceDetails CreateFromRunspace(
Runspace runspace,
- SessionDetails sessionDetails)
+ SessionDetails sessionDetails,
+ ILogger logger)
{
Validate.IsNotNull(nameof(runspace), runspace);
Validate.IsNotNull(nameof(sessionDetails), sessionDetails);
@@ -194,7 +196,7 @@ internal static RunspaceDetails CreateFromRunspace(
var runspaceId = runspace.InstanceId;
var runspaceLocation = RunspaceLocation.Local;
var runspaceContext = RunspaceContext.Original;
- var versionDetails = PowerShellVersionDetails.GetVersionDetails(runspace);
+ var versionDetails = PowerShellVersionDetails.GetVersionDetails(runspace, logger);
string connectionString = null;
diff --git a/src/PowerShellEditorServices/Session/SessionPSHost.cs b/src/PowerShellEditorServices/Session/SessionPSHost.cs
index 41e4cec7a..cc54438ec 100644
--- a/src/PowerShellEditorServices/Session/SessionPSHost.cs
+++ b/src/PowerShellEditorServices/Session/SessionPSHost.cs
@@ -151,7 +151,7 @@ public override PSHostUserInterface UI
///
public override void EnterNestedPrompt()
{
- Logger.Write(LogLevel.Verbose, "EnterNestedPrompt() called.");
+ Logger.CurrentLogger.Write(LogLevel.Verbose, "EnterNestedPrompt() called.");
}
///
@@ -159,7 +159,7 @@ public override void EnterNestedPrompt()
///
public override void ExitNestedPrompt()
{
- Logger.Write(LogLevel.Verbose, "ExitNestedPrompt() called.");
+ Logger.CurrentLogger.Write(LogLevel.Verbose, "ExitNestedPrompt() called.");
}
///
@@ -167,7 +167,7 @@ public override void ExitNestedPrompt()
///
public override void NotifyBeginApplication()
{
- Logger.Write(LogLevel.Verbose, "NotifyBeginApplication() called.");
+ Logger.CurrentLogger.Write(LogLevel.Verbose, "NotifyBeginApplication() called.");
this.isNativeApplicationRunning = true;
}
@@ -176,7 +176,7 @@ public override void NotifyBeginApplication()
///
public override void NotifyEndApplication()
{
- Logger.Write(LogLevel.Verbose, "NotifyEndApplication() called.");
+ Logger.CurrentLogger.Write(LogLevel.Verbose, "NotifyEndApplication() called.");
this.isNativeApplicationRunning = false;
}
diff --git a/src/PowerShellEditorServices/Session/SessionPSHostRawUserInterface.cs b/src/PowerShellEditorServices/Session/SessionPSHostRawUserInterface.cs
index 07caf165d..6f4d5bfae 100644
--- a/src/PowerShellEditorServices/Session/SessionPSHostRawUserInterface.cs
+++ b/src/PowerShellEditorServices/Session/SessionPSHostRawUserInterface.cs
@@ -168,7 +168,7 @@ public override Size MaxWindowSize
/// A KeyInfo struct with details about the current keypress.
public override KeyInfo ReadKey(ReadKeyOptions options)
{
- Logger.Write(
+ Logger.CurrentLogger.Write(
LogLevel.Warning,
"PSHostRawUserInterface.ReadKey was called");
@@ -180,7 +180,7 @@ public override KeyInfo ReadKey(ReadKeyOptions options)
///
public override void FlushInputBuffer()
{
- Logger.Write(
+ Logger.CurrentLogger.Write(
LogLevel.Warning,
"PSHostRawUserInterface.FlushInputBuffer was called");
}
@@ -192,7 +192,7 @@ public override void FlushInputBuffer()
/// A BufferCell array with the requested buffer contents.
public override BufferCell[,] GetBufferContents(Rectangle rectangle)
{
- Logger.Write(
+ Logger.CurrentLogger.Write(
LogLevel.Warning,
"PSHostRawUserInterface.GetBufferContents was called");
@@ -212,7 +212,7 @@ public override void ScrollBufferContents(
Rectangle clip,
BufferCell fill)
{
- Logger.Write(
+ Logger.CurrentLogger.Write(
LogLevel.Warning,
"PSHostRawUserInterface.ScrollBufferContents was called");
}
@@ -236,7 +236,7 @@ public override void SetBufferContents(
}
else
{
- Logger.Write(
+ Logger.CurrentLogger.Write(
LogLevel.Warning,
"PSHostRawUserInterface.SetBufferContents was called with a specific region");
}
@@ -251,7 +251,7 @@ public override void SetBufferContents(
Coordinates origin,
BufferCell[,] contents)
{
- Logger.Write(
+ Logger.CurrentLogger.Write(
LogLevel.Warning,
"PSHostRawUserInterface.SetBufferContents was called");
}
diff --git a/src/PowerShellEditorServices/Session/SessionPSHostUserInterface.cs b/src/PowerShellEditorServices/Session/SessionPSHostUserInterface.cs
index 5a50ab127..968a98110 100644
--- a/src/PowerShellEditorServices/Session/SessionPSHostUserInterface.cs
+++ b/src/PowerShellEditorServices/Session/SessionPSHostUserInterface.cs
@@ -13,6 +13,7 @@
using System.Threading.Tasks;
using Microsoft.PowerShell.EditorServices.Console;
using System.Threading;
+using Microsoft.PowerShell.EditorServices.Utility;
namespace Microsoft.PowerShell.EditorServices
{
@@ -89,7 +90,7 @@ public override Dictionary Prompt(
{
FieldDetails[] fields =
fieldDescriptions
- .Select(FieldDetails.Create)
+ .Select(f => { return FieldDetails.Create(f, Logger.CurrentLogger); })
.ToArray();
CancellationTokenSource cancellationToken = new CancellationTokenSource();
diff --git a/src/PowerShellEditorServices/Session/SimplePSHostRawUserInterface.cs b/src/PowerShellEditorServices/Session/SimplePSHostRawUserInterface.cs
index fbb3057a2..85993107f 100644
--- a/src/PowerShellEditorServices/Session/SimplePSHostRawUserInterface.cs
+++ b/src/PowerShellEditorServices/Session/SimplePSHostRawUserInterface.cs
@@ -159,7 +159,7 @@ public override Size MaxWindowSize
/// A KeyInfo struct with details about the current keypress.
public override KeyInfo ReadKey(ReadKeyOptions options)
{
- Logger.Write(
+ Logger.CurrentLogger.Write(
LogLevel.Warning,
"PSHostRawUserInterface.ReadKey was called");
@@ -171,7 +171,7 @@ public override KeyInfo ReadKey(ReadKeyOptions options)
///
public override void FlushInputBuffer()
{
- Logger.Write(
+ Logger.CurrentLogger.Write(
LogLevel.Warning,
"PSHostRawUserInterface.FlushInputBuffer was called");
}
@@ -183,7 +183,7 @@ public override void FlushInputBuffer()
/// A BufferCell array with the requested buffer contents.
public override BufferCell[,] GetBufferContents(Rectangle rectangle)
{
- Logger.Write(
+ Logger.CurrentLogger.Write(
LogLevel.Warning,
"PSHostRawUserInterface.GetBufferContents was called");
@@ -203,7 +203,7 @@ public override void ScrollBufferContents(
Rectangle clip,
BufferCell fill)
{
- Logger.Write(
+ Logger.CurrentLogger.Write(
LogLevel.Warning,
"PSHostRawUserInterface.ScrollBufferContents was called");
}
@@ -217,7 +217,7 @@ public override void SetBufferContents(
Rectangle rectangle,
BufferCell fill)
{
- Logger.Write(
+ Logger.CurrentLogger.Write(
LogLevel.Warning,
"PSHostRawUserInterface.SetBufferContents was called");
}
@@ -231,7 +231,7 @@ public override void SetBufferContents(
Coordinates origin,
BufferCell[,] contents)
{
- Logger.Write(
+ Logger.CurrentLogger.Write(
LogLevel.Warning,
"PSHostRawUserInterface.SetBufferContents was called");
}
diff --git a/src/PowerShellEditorServices/Templates/TemplateService.cs b/src/PowerShellEditorServices/Templates/TemplateService.cs
index fe3a39af2..8ee3da496 100644
--- a/src/PowerShellEditorServices/Templates/TemplateService.cs
+++ b/src/PowerShellEditorServices/Templates/TemplateService.cs
@@ -20,6 +20,7 @@ public class TemplateService
{
#region Private Fields
+ private ILogger logger;
private bool isPlasterLoaded;
private bool? isPlasterInstalled;
private PowerShellContext powerShellContext;
@@ -32,10 +33,12 @@ public class TemplateService
/// Creates a new instance of the TemplateService class.
///
/// The PowerShellContext to use for this service.
- public TemplateService(PowerShellContext powerShellContext)
+ /// An ILogger implementation used for writing log messages.
+ public TemplateService(PowerShellContext powerShellContext, ILogger logger)
{
Validate.IsNotNull(nameof(powerShellContext), powerShellContext);
+ this.logger = logger;
this.powerShellContext = powerShellContext;
}
@@ -67,7 +70,7 @@ public async Task ImportPlasterIfInstalled()
.AddCommand("Select-Object")
.AddParameter("First", 1);
- Logger.Write(LogLevel.Verbose, "Checking if Plaster is installed...");
+ this.logger.Write(LogLevel.Verbose, "Checking if Plaster is installed...");
var getResult =
await this.powerShellContext.ExecuteCommand(
@@ -75,18 +78,18 @@ await this.powerShellContext.ExecuteCommand(
PSObject moduleObject = getResult.First();
this.isPlasterInstalled = moduleObject != null;
- string installedQualifier =
+ string installedQualifier =
this.isPlasterInstalled.Value
? string.Empty : "not ";
- Logger.Write(
+ this.logger.Write(
LogLevel.Verbose,
$"Plaster is {installedQualifier}installed!");
// Attempt to load plaster
if (this.isPlasterInstalled.Value && this.isPlasterLoaded == false)
{
- Logger.Write(LogLevel.Verbose, "Loading Plaster...");
+ this.logger.Write(LogLevel.Verbose, "Loading Plaster...");
psCommand = new PSCommand();
psCommand
@@ -103,7 +106,7 @@ await this.powerShellContext.ExecuteCommand(
this.isPlasterInstalled.Value
? "was" : "could not be";
- Logger.Write(
+ this.logger.Write(
LogLevel.Verbose,
$"Plaster {loadedQualifier} loaded successfully!");
}
@@ -141,7 +144,7 @@ public async Task GetAvailableTemplates(
await this.powerShellContext.ExecuteCommand(
psCommand, false, false);
- Logger.Write(
+ this.logger.Write(
LogLevel.Verbose,
$"Found {templateObjects.Count()} Plaster templates");
@@ -163,7 +166,7 @@ public async Task CreateFromTemplate(
string templatePath,
string destinationPath)
{
- Logger.Write(
+ this.logger.Write(
LogLevel.Verbose,
$"Invoking Plaster...\n\n TemplatePath: {templatePath}\n DestinationPath: {destinationPath}");
diff --git a/src/PowerShellEditorServices/Utility/AsyncContext.cs b/src/PowerShellEditorServices/Utility/AsyncContext.cs
index 421ca3d96..ece383173 100644
--- a/src/PowerShellEditorServices/Utility/AsyncContext.cs
+++ b/src/PowerShellEditorServices/Utility/AsyncContext.cs
@@ -23,7 +23,8 @@ public static class AsyncContext
/// The Task-returning Func which represents the "main" function
/// for the thread.
///
- public static void Start(Func asyncMainFunc)
+ /// An ILogger implementation used for writing log messages.
+ public static void Start(Func asyncMainFunc, ILogger logger)
{
// Is there already a synchronization context?
if (SynchronizationContext.Current != null)
@@ -33,7 +34,7 @@ public static void Start(Func asyncMainFunc)
}
// Create and register a synchronization context for this thread
- var threadSyncContext = new ThreadSynchronizationContext();
+ var threadSyncContext = new ThreadSynchronizationContext(logger);
SynchronizationContext.SetSynchronizationContext(threadSyncContext);
// Get the main task and act on its completion
diff --git a/src/PowerShellEditorServices/Utility/AsyncContextThread.cs b/src/PowerShellEditorServices/Utility/AsyncContextThread.cs
index 92629437a..c5ca20039 100644
--- a/src/PowerShellEditorServices/Utility/AsyncContextThread.cs
+++ b/src/PowerShellEditorServices/Utility/AsyncContextThread.cs
@@ -47,10 +47,11 @@ public AsyncContextThread(string threadName)
///
/// A Func which returns the task to be run on the thread.
///
+ /// An ILogger implementation used for writing log messages.
///
/// A Task which can be used to monitor the thread for completion.
///
- public Task Run(Func taskReturningFunc)
+ public Task Run(Func taskReturningFunc, ILogger logger)
{
// Start up a long-running task with the action as the
// main entry point for the thread
@@ -62,7 +63,7 @@ public Task Run(Func taskReturningFunc)
Thread.CurrentThread.Name = "AsyncContextThread: " + this.threadName;
// Set up an AsyncContext to run the task
- AsyncContext.Start(taskReturningFunc);
+ AsyncContext.Start(taskReturningFunc, logger);
},
this.threadCancellationToken.Token,
TaskCreationOptions.LongRunning,
diff --git a/src/PowerShellEditorServices/Utility/FileLogger.cs b/src/PowerShellEditorServices/Utility/FileLogger.cs
new file mode 100644
index 000000000..731d56c0e
--- /dev/null
+++ b/src/PowerShellEditorServices/Utility/FileLogger.cs
@@ -0,0 +1,174 @@
+//
+// 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.IO;
+using System.Runtime.CompilerServices;
+using System.Text;
+using System.Threading;
+
+namespace Microsoft.PowerShell.EditorServices.Utility
+{
+ ///
+ /// Provides an implementation of ILogger for writing messages to
+ /// a log file on disk.
+ ///
+ public class FileLogger : ILogger, IDisposable
+ {
+ private TextWriter textWriter;
+ private LogLevel minimumLogLevel = LogLevel.Verbose;
+
+ ///
+ /// Creates an ILogger implementation that writes to the specified file.
+ ///
+ ///
+ /// Specifies the path at which log messages will be written.
+ ///
+ ///
+ /// Specifies the minimum log message level to write to the log file.
+ ///
+ public FileLogger(string logFilePath, LogLevel minimumLogLevel)
+ {
+ this.minimumLogLevel = minimumLogLevel;
+
+ // Ensure that we have a usable log file path
+ if (!Path.IsPathRooted(logFilePath))
+ {
+ logFilePath =
+ Path.Combine(
+#if CoreCLR
+ AppContext.BaseDirectory,
+#else
+ AppDomain.CurrentDomain.BaseDirectory,
+#endif
+ logFilePath);
+ }
+
+ if (!this.TryOpenLogFile(logFilePath))
+ {
+ // If the log file couldn't be opened at this location,
+ // try opening it in a more reliable path
+ this.TryOpenLogFile(
+ Path.Combine(
+#if CoreCLR
+ Environment.GetEnvironmentVariable("TEMP"),
+#else
+ Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData),
+#endif
+ Path.GetFileName(logFilePath)));
+ }
+ }
+
+ ///
+ /// Writes a message to the log file.
+ ///
+ /// The level at which the message will be written.
+ /// The message text to be written.
+ /// The name of the calling method.
+ /// The source file path where the calling method exists.
+ /// The line number of the calling method.
+ public void Write(
+ LogLevel logLevel,
+ string logMessage,
+ string callerName = null,
+ string callerSourceFile = null,
+ int callerLineNumber = 0)
+ {
+ if (this.textWriter != null &&
+ logLevel >= this.minimumLogLevel)
+ {
+ // Print the timestamp and log level
+ this.textWriter.WriteLine(
+ "{0} [{1}] - Method \"{2}\" at line {3} of {4}\r\n",
+ DateTime.Now,
+ logLevel.ToString().ToUpper(),
+ callerName,
+ callerLineNumber,
+ callerSourceFile);
+
+ // Print out indented message lines
+ foreach (var messageLine in logMessage.Split('\n'))
+ {
+ this.textWriter.WriteLine(" " + messageLine.TrimEnd());
+ }
+
+ // Finish with a newline and flush the writer
+ this.textWriter.WriteLine();
+ this.textWriter.Flush();
+ }
+ }
+
+ ///
+ /// Writes an error message and exception to the log file.
+ ///
+ /// The error message text to be written.
+ /// The exception to be written..
+ /// The name of the calling method.
+ /// The source file path where the calling method exists.
+ /// The line number of the calling method.
+ public void WriteException(
+ string errorMessage,
+ Exception errorException,
+ [CallerMemberName] string callerName = null,
+ [CallerFilePath] string callerSourceFile = null,
+ [CallerLineNumber] int callerLineNumber = 0)
+ {
+ this.Write(
+ LogLevel.Error,
+ $"{errorMessage}\r\n\r\n{errorException.ToString()}",
+ callerName,
+ callerSourceFile,
+ callerLineNumber);
+ }
+
+ ///
+ /// Flushes any remaining log write and closes the log file.
+ ///
+ public void Dispose()
+ {
+ if (this.textWriter != null)
+ {
+ this.textWriter.Flush();
+ this.textWriter.Dispose();
+ this.textWriter = null;
+ }
+ }
+
+ private bool TryOpenLogFile(string logFilePath)
+ {
+ try
+ {
+ // Make sure the log directory exists
+ Directory.CreateDirectory(
+ Path.GetDirectoryName(
+ logFilePath));
+
+ // Open the log file for writing with UTF8 encoding
+ this.textWriter =
+ new StreamWriter(
+ new FileStream(
+ logFilePath,
+ FileMode.Create),
+ Encoding.UTF8);
+
+ return true;
+ }
+ catch (Exception e)
+ {
+ if (e is UnauthorizedAccessException ||
+ e is IOException)
+ {
+ // This exception is thrown when we can't open the file
+ // at the path in logFilePath. Return false to indicate
+ // that the log file couldn't be created.
+ return false;
+ }
+
+ // Unexpected exception, rethrow it
+ throw;
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/PowerShellEditorServices/Utility/ILogger.cs b/src/PowerShellEditorServices/Utility/ILogger.cs
new file mode 100644
index 000000000..e5c91afd4
--- /dev/null
+++ b/src/PowerShellEditorServices/Utility/ILogger.cs
@@ -0,0 +1,75 @@
+//
+// 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.IO;
+using System.Runtime.CompilerServices;
+using System.Text;
+using System.Threading;
+
+namespace Microsoft.PowerShell.EditorServices.Utility
+{
+ ///
+ /// Defines the level indicators for log messages.
+ ///
+ public enum LogLevel
+ {
+ ///
+ /// Indicates a verbose log message.
+ ///
+ Verbose,
+
+ ///
+ /// Indicates a normal, non-verbose log message.
+ ///
+ Normal,
+
+ ///
+ /// Indicates a warning message.
+ ///
+ Warning,
+
+ ///
+ /// Indicates an error message.
+ ///
+ Error
+ }
+
+ ///
+ /// Defines an interface for writing messages to a logging implementation.
+ ///
+ public interface ILogger : IDisposable
+ {
+ ///
+ /// Writes a message to the log file.
+ ///
+ /// The level at which the message will be written.
+ /// The message text to be written.
+ /// The name of the calling method.
+ /// The source file path where the calling method exists.
+ /// The line number of the calling method.
+ void Write(
+ LogLevel logLevel,
+ string logMessage,
+ [CallerMemberName] string callerName = null,
+ [CallerFilePath] string callerSourceFile = null,
+ [CallerLineNumber] int callerLineNumber = 0);
+
+ ///
+ /// Writes an error message and exception to the log file.
+ ///
+ /// The error message text to be written.
+ /// The exception to be written..
+ /// The name of the calling method.
+ /// The source file path where the calling method exists.
+ /// The line number of the calling method.
+ void WriteException(
+ string errorMessage,
+ Exception errorException,
+ [CallerMemberName] string callerName = null,
+ [CallerFilePath] string callerSourceFile = null,
+ [CallerLineNumber] int callerLineNumber = 0);
+ }
+}
\ No newline at end of file
diff --git a/src/PowerShellEditorServices/Utility/Logger.cs b/src/PowerShellEditorServices/Utility/Logger.cs
index fd072a7ad..930fcc369 100644
--- a/src/PowerShellEditorServices/Utility/Logger.cs
+++ b/src/PowerShellEditorServices/Utility/Logger.cs
@@ -3,71 +3,34 @@
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
//
-using System;
-using System.IO;
-using System.Runtime.CompilerServices;
-using System.Text;
-
namespace Microsoft.PowerShell.EditorServices.Utility
{
- ///
- /// Defines the level indicators for log messages.
- ///
- public enum LogLevel
- {
- ///
- /// Indicates a verbose log message.
- ///
- Verbose,
-
- ///
- /// Indicates a normal, non-verbose log message.
- ///
- Normal,
-
- ///
- /// Indicates a warning message.
- ///
- Warning,
-
- ///
- /// Indicates an error message.
- ///
- Error
- }
-
///
/// Provides a simple logging interface. May be replaced with a
/// more robust solution at a later date.
///
public static class Logger
{
- private static LogWriter logWriter;
+ ///
+ /// Gets the current static ILogger instance. This property
+ /// is temporary and will be removed in an upcoming commit.
+ ///
+ public static ILogger CurrentLogger { get; private set; }
///
/// Initializes the Logger for the current session.
///
- ///
- /// Optional. Specifies the path at which log messages will be written.
+ ///
+ /// Specifies the ILogger implementation to use for the static interface.
///
- ///
- /// Optional. Specifies the minimum log message level to write to the log file.
- ///
- public static void Initialize(
- string logFilePath = "EditorServices.log",
- LogLevel minimumLogLevel = LogLevel.Normal)
+ public static void Initialize(ILogger logger)
{
- if (logWriter != null)
+ if (CurrentLogger != null)
{
- logWriter.Dispose();
+ CurrentLogger.Dispose();
}
- // TODO: Parameterize this
- logWriter =
- new LogWriter(
- minimumLogLevel,
- logFilePath,
- true);
+ CurrentLogger = logger;
}
///
@@ -75,217 +38,9 @@ public static void Initialize(
///
public static void Close()
{
- if (logWriter != null)
- {
- logWriter.Dispose();
- }
- }
-
- ///
- /// Writes a message to the log file.
- ///
- /// The level at which the message will be written.
- /// The message text to be written.
- /// The name of the calling method.
- /// The source file path where the calling method exists.
- /// The line number of the calling method.
- public static void Write(
- LogLevel logLevel,
- string logMessage,
- [CallerMemberName] string callerName = null,
- [CallerFilePath] string callerSourceFile = null,
- [CallerLineNumber] int callerLineNumber = 0)
- {
- InnerWrite(
- logLevel,
- logMessage,
- callerName,
- callerSourceFile,
- callerLineNumber);
- }
-
- ///
- /// Writes an error message and exception to the log file.
- ///
- /// The error message text to be written.
- /// The exception to be written..
- /// The name of the calling method.
- /// The source file path where the calling method exists.
- /// The line number of the calling method.
- public static void WriteException(
- string errorMessage,
- Exception errorException,
- [CallerMemberName] string callerName = null,
- [CallerFilePath] string callerSourceFile = null,
- [CallerLineNumber] int callerLineNumber = 0)
- {
- InnerWrite(
- LogLevel.Error,
- $"{errorMessage}\r\n\r\n{errorException.ToString()}",
- callerName,
- callerSourceFile,
- callerLineNumber);
- }
-
- ///
- /// Writes an error message and exception to the log file.
- ///
- /// The level at which the message will be written.
- /// The error message text to be written.
- /// The exception to be written..
- /// The name of the calling method.
- /// The source file path where the calling method exists.
- /// The line number of the calling method.
- public static void WriteException(
- LogLevel logLevel,
- string errorMessage,
- Exception errorException,
- [CallerMemberName] string callerName = null,
- [CallerFilePath] string callerSourceFile = null,
- [CallerLineNumber] int callerLineNumber = 0)
- {
- InnerWrite(
- logLevel,
- $"{errorMessage}\r\n\r\n{errorException.ToString()}",
- callerName,
- callerSourceFile,
- callerLineNumber);
- }
-
- private static void InnerWrite(
- LogLevel logLevel,
- string logMessage,
- string callerName,
- string callerSourceFile,
- int callerLineNumber)
- {
- if (logWriter != null)
+ if (CurrentLogger != null)
{
- logWriter.Write(
- logLevel,
- logMessage,
- callerName,
- callerSourceFile,
- callerLineNumber);
- }
- }
- }
-
- internal class LogWriter : IDisposable
- {
- private TextWriter textWriter;
- private LogLevel minimumLogLevel = LogLevel.Verbose;
-
- public LogWriter(LogLevel minimumLogLevel, string logFilePath, bool deleteExisting)
- {
- this.minimumLogLevel = minimumLogLevel;
-
- // Ensure that we have a usable log file path
- if (!Path.IsPathRooted(logFilePath))
- {
- logFilePath =
- Path.Combine(
-#if CoreCLR
- AppContext.BaseDirectory,
-#else
- AppDomain.CurrentDomain.BaseDirectory,
-#endif
- logFilePath);
- }
-
- if (!this.TryOpenLogFile(logFilePath, deleteExisting))
- {
- // If the log file couldn't be opened at this location,
- // try opening it in a more reliable path
- this.TryOpenLogFile(
- Path.Combine(
-#if CoreCLR
- Environment.GetEnvironmentVariable("TEMP"),
-#else
- Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData),
-#endif
- Path.GetFileName(logFilePath)),
- deleteExisting);
- }
- }
-
- public void Write(
- LogLevel logLevel,
- string logMessage,
- string callerName = null,
- string callerSourceFile = null,
- int callerLineNumber = 0)
- {
- if (this.textWriter != null &&
- logLevel >= this.minimumLogLevel)
- {
- // Print the timestamp and log level
- this.textWriter.WriteLine(
- "{0} [{1}] - Method \"{2}\" at line {3} of {4}\r\n",
- DateTime.Now,
- logLevel.ToString().ToUpper(),
- callerName,
- callerLineNumber,
- callerSourceFile);
-
- // Print out indented message lines
- foreach (var messageLine in logMessage.Split('\n'))
- {
- this.textWriter.WriteLine(" " + messageLine.TrimEnd());
- }
-
- // Finish with a newline and flush the writer
- this.textWriter.WriteLine();
- this.textWriter.Flush();
- }
- }
-
- public void Dispose()
- {
- if (this.textWriter != null)
- {
- this.textWriter.Flush();
- this.textWriter.Dispose();
- this.textWriter = null;
- }
- }
-
- private bool TryOpenLogFile(
- string logFilePath,
- bool deleteExisting)
- {
- try
- {
- // Make sure the log directory exists
- Directory.CreateDirectory(
- Path.GetDirectoryName(
- logFilePath));
-
- // Open the log file for writing with UTF8 encoding
- this.textWriter =
- new StreamWriter(
- new FileStream(
- logFilePath,
- deleteExisting ?
- FileMode.Create :
- FileMode.Append),
- Encoding.UTF8);
-
- return true;
- }
- catch (Exception e)
- {
- if (e is UnauthorizedAccessException ||
- e is IOException)
- {
- // This exception is thrown when we can't open the file
- // at the path in logFilePath. Return false to indicate
- // that the log file couldn't be created.
- return false;
- }
-
- // Unexpected exception, rethrow it
- throw;
+ CurrentLogger.Dispose();
}
}
}
diff --git a/src/PowerShellEditorServices/Utility/NullLogger.cs b/src/PowerShellEditorServices/Utility/NullLogger.cs
new file mode 100644
index 000000000..d94528e5d
--- /dev/null
+++ b/src/PowerShellEditorServices/Utility/NullLogger.cs
@@ -0,0 +1,61 @@
+//
+// 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.IO;
+using System.Runtime.CompilerServices;
+using System.Text;
+using System.Threading;
+
+namespace Microsoft.PowerShell.EditorServices.Utility
+{
+ ///
+ /// Provides an implementation of ILogger that throws away all log messages,
+ /// typically used when logging isn't needed.
+ ///
+ public class NullLogger : ILogger, IDisposable
+ {
+ ///
+ /// Writes a message to the log file.
+ ///
+ /// The level at which the message will be written.
+ /// The message text to be written.
+ /// The name of the calling method.
+ /// The source file path where the calling method exists.
+ /// The line number of the calling method.
+ public void Write(
+ LogLevel logLevel,
+ string logMessage,
+ string callerName = null,
+ string callerSourceFile = null,
+ int callerLineNumber = 0)
+ {
+ }
+
+ ///
+ /// Writes an error message and exception to the log file.
+ ///
+ /// The error message text to be written.
+ /// The exception to be written..
+ /// The name of the calling method.
+ /// The source file path where the calling method exists.
+ /// The line number of the calling method.
+ public void WriteException(
+ string errorMessage,
+ Exception errorException,
+ [CallerMemberName] string callerName = null,
+ [CallerFilePath] string callerSourceFile = null,
+ [CallerLineNumber] int callerLineNumber = 0)
+ {
+ }
+
+ ///
+ /// Flushes any remaining log write and closes the log file.
+ ///
+ public void Dispose()
+ {
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/PowerShellEditorServices/Utility/ThreadSynchronizationContext.cs b/src/PowerShellEditorServices/Utility/ThreadSynchronizationContext.cs
index 8acda7091..77db1d113 100644
--- a/src/PowerShellEditorServices/Utility/ThreadSynchronizationContext.cs
+++ b/src/PowerShellEditorServices/Utility/ThreadSynchronizationContext.cs
@@ -18,6 +18,7 @@ public class ThreadSynchronizationContext : SynchronizationContext
{
#region Private Fields
+ private ILogger logger;
private BlockingCollection> requestQueue =
new BlockingCollection>();
@@ -25,6 +26,19 @@ public class ThreadSynchronizationContext : SynchronizationContext
#region Constructors
+ ///
+ ///
+ ///
+ /// An ILogger implementation used for writing log messages.
+ public ThreadSynchronizationContext(ILogger logger)
+ {
+ this.logger = logger;
+ }
+
+ #endregion
+
+ #region Public Methods
+
///
/// Posts a request for execution to the SynchronizationContext.
/// This will be executed on the SynchronizationContext's thread.
@@ -47,7 +61,7 @@ public override void Post(SendOrPostCallback callback, object state)
}
else
{
- Logger.Write(
+ this.logger.Write(
LogLevel.Verbose,
"Attempted to post message to synchronization context after it's already completed");
}
diff --git a/src/PowerShellEditorServices/Workspace/Workspace.cs b/src/PowerShellEditorServices/Workspace/Workspace.cs
index 283831d17..30bce240c 100644
--- a/src/PowerShellEditorServices/Workspace/Workspace.cs
+++ b/src/PowerShellEditorServices/Workspace/Workspace.cs
@@ -21,6 +21,7 @@ public class Workspace
{
#region Private Fields
+ private ILogger logger;
private Version powerShellVersion;
private Dictionary workspaceFiles = new Dictionary();
@@ -41,9 +42,11 @@ public class Workspace
/// Creates a new instance of the Workspace class.
///
/// The version of PowerShell for which scripts will be parsed.
- public Workspace(Version powerShellVersion)
+ /// An ILogger implementation used for writing log messages.
+ public Workspace(Version powerShellVersion, ILogger logger)
{
this.powerShellVersion = powerShellVersion;
+ this.logger = logger;
}
#endregion
@@ -88,7 +91,7 @@ public ScriptFile GetFile(string filePath)
this.workspaceFiles.Add(keyName, scriptFile);
}
- Logger.Write(LogLevel.Verbose, "Opened file on disk: " + resolvedFilePath);
+ this.logger.Write(LogLevel.Verbose, "Opened file on disk: " + resolvedFilePath);
}
return scriptFile;
@@ -132,7 +135,7 @@ public ScriptFile GetFileBuffer(string filePath, string initialBuffer)
this.workspaceFiles.Add(keyName, scriptFile);
- Logger.Write(LogLevel.Verbose, "Opened file as in-memory buffer: " + resolvedFilePath);
+ this.logger.Write(LogLevel.Verbose, "Opened file as in-memory buffer: " + resolvedFilePath);
}
return scriptFile;
@@ -248,7 +251,7 @@ private IEnumerable RecursivelyEnumerateFiles(string folderPath)
}
catch (UnauthorizedAccessException e)
{
- Logger.WriteException(
+ this.logger.WriteException(
$"Could not enumerate files in the path '{folderPath}' due to the path not being accessible",
e);
}
@@ -265,7 +268,7 @@ private IEnumerable RecursivelyEnumerateFiles(string folderPath)
}
catch (UnauthorizedAccessException e)
{
- Logger.WriteException(
+ this.logger.WriteException(
$"Could not enumerate files in the path '{folderPath}' due to a file not being accessible",
e);
}
@@ -303,7 +306,7 @@ private void RecursivelyFindReferences(
continue;
}
- Logger.Write(
+ this.logger.Write(
LogLevel.Verbose,
string.Format(
"Resolved relative path '{0}' to '{1}'",
@@ -348,7 +351,7 @@ private string ResolveFilePath(string filePath)
filePath = Path.GetFullPath(filePath);
}
- Logger.Write(LogLevel.Verbose, "Resolved path: " + filePath);
+ this.logger.Write(LogLevel.Verbose, "Resolved path: " + filePath);
return filePath;
}
@@ -428,7 +431,7 @@ private string ResolveRelativeScriptPath(string baseFilePath, string relativePat
if (resolveException != null)
{
- Logger.Write(
+ this.logger.Write(
LogLevel.Error,
$"Could not resolve relative script path\r\n" +
$" baseFilePath = {baseFilePath}\r\n " +
diff --git a/test/PowerShellEditorServices.Test.Host/DebugAdapterTests.cs b/test/PowerShellEditorServices.Test.Host/DebugAdapterTests.cs
index 66220b52b..071a776d0 100644
--- a/test/PowerShellEditorServices.Test.Host/DebugAdapterTests.cs
+++ b/test/PowerShellEditorServices.Test.Host/DebugAdapterTests.cs
@@ -17,6 +17,7 @@ namespace Microsoft.PowerShell.EditorServices.Test.Host
{
public class DebugAdapterTests : ServerTestsBase, IAsyncLifetime
{
+ private ILogger logger;
private DebugAdapterClient debugAdapterClient;
private string DebugScriptPath =
Path.GetFullPath(@"..\..\..\..\PowerShellEditorServices.Test.Shared\Debugging\DebugTest.ps1");
@@ -34,9 +35,12 @@ public async Task InitializeAsync()
this.GetType().Name,
Guid.NewGuid().ToString().Substring(0, 8));
- Logger.Initialize(
- testLogPath + "-client.log",
- LogLevel.Verbose);
+ this.logger =
+ new FileLogger(
+ testLogPath + "-client.log",
+ LogLevel.Verbose);
+
+ Logger.Initialize(this.logger);
testLogPath += "-server.log";
System.Console.WriteLine(" Output log at path: {0}", testLogPath);
@@ -52,7 +56,9 @@ await this.LaunchService(
new DebugAdapterClient(
await TcpSocketClientChannel.Connect(
portNumbers.Item2,
- MessageProtocolType.DebugAdapter));
+ MessageProtocolType.DebugAdapter,
+ this.logger),
+ this.logger);
await this.debugAdapterClient.Start();
}
diff --git a/test/PowerShellEditorServices.Test.Host/LanguageServerTests.cs b/test/PowerShellEditorServices.Test.Host/LanguageServerTests.cs
index 64d682e05..ee32eb63f 100644
--- a/test/PowerShellEditorServices.Test.Host/LanguageServerTests.cs
+++ b/test/PowerShellEditorServices.Test.Host/LanguageServerTests.cs
@@ -22,6 +22,7 @@ namespace Microsoft.PowerShell.EditorServices.Test.Host
{
public class LanguageServerTests : ServerTestsBase, IAsyncLifetime
{
+ private ILogger logger;
private LanguageServiceClient languageServiceClient;
public async Task InitializeAsync()
@@ -37,9 +38,12 @@ public async Task InitializeAsync()
this.GetType().Name,
Guid.NewGuid().ToString().Substring(0, 8));
- Logger.Initialize(
- testLogPath + "-client.log",
- LogLevel.Verbose);
+ this.logger =
+ new FileLogger(
+ testLogPath + "-client.log",
+ LogLevel.Verbose);
+
+ Logger.Initialize(this.logger);
testLogPath += "-server.log";
System.Console.WriteLine(" Output log at path: {0}", testLogPath);
@@ -55,7 +59,9 @@ await this.LaunchService(
new LanguageServiceClient(
await TcpSocketClientChannel.Connect(
portNumbers.Item1,
- MessageProtocolType.LanguageServer));
+ MessageProtocolType.LanguageServer,
+ this.logger),
+ this.logger);
await this.languageServiceClient.Start();
}
diff --git a/test/PowerShellEditorServices.Test.Protocol/Message/MessageReaderWriterTests.cs b/test/PowerShellEditorServices.Test.Protocol/Message/MessageReaderWriterTests.cs
index a82df2991..42ab1ea41 100644
--- a/test/PowerShellEditorServices.Test.Protocol/Message/MessageReaderWriterTests.cs
+++ b/test/PowerShellEditorServices.Test.Protocol/Message/MessageReaderWriterTests.cs
@@ -10,6 +10,7 @@
using System.Text;
using System.Threading.Tasks;
using Xunit;
+using Microsoft.PowerShell.EditorServices.Utility;
namespace Microsoft.PowerShell.EditorServices.Test.Protocol.MessageProtocol
{
@@ -19,10 +20,12 @@ public class MessageReaderWriterTests
const string TestEventFormatString = "{{\"event\":\"testEvent\",\"body\":{{\"someString\":\"{0}\"}},\"seq\":0,\"type\":\"event\"}}";
readonly int ExpectedMessageByteCount = Encoding.UTF8.GetByteCount(TestEventString);
+ private ILogger logger;
private IMessageSerializer messageSerializer;
public MessageReaderWriterTests()
{
+ this.logger = new NullLogger();
this.messageSerializer = new V8MessageSerializer();
}
@@ -31,10 +34,11 @@ public async Task WritesMessage()
{
MemoryStream outputStream = new MemoryStream();
- MessageWriter messageWriter =
+ MessageWriter messageWriter =
new MessageWriter(
outputStream,
- this.messageSerializer);
+ this.messageSerializer,
+ this.logger);
// Write the message and then roll back the stream to be read
// TODO: This will need to be redone!
@@ -69,8 +73,9 @@ public void ReadsMessage()
MemoryStream inputStream = new MemoryStream();
MessageReader messageReader =
new MessageReader(
- inputStream,
- this.messageSerializer);
+ inputStream,
+ this.messageSerializer,
+ this.logger);
// Write a message to the stream
byte[] messageBuffer = this.GetMessageBytes(TestEventString);
@@ -94,8 +99,9 @@ public void ReadsManyBufferedMessages()
MemoryStream inputStream = new MemoryStream();
MessageReader messageReader =
new MessageReader(
- inputStream,
- this.messageSerializer);
+ inputStream,
+ this.messageSerializer,
+ this.logger);
// Get a message to use for writing to the stream
byte[] messageBuffer = this.GetMessageBytes(TestEventString);
@@ -130,12 +136,13 @@ public void ReaderResizesBufferForLargeMessages()
MemoryStream inputStream = new MemoryStream();
MessageReader messageReader =
new MessageReader(
- inputStream,
- this.messageSerializer);
+ inputStream,
+ this.messageSerializer,
+ this.logger);
// Get a message with content so large that the buffer will need
// to be resized to fit it all.
- byte[] messageBuffer =
+ byte[] messageBuffer =
this.GetMessageBytes(
string.Format(
TestEventFormatString,
@@ -159,7 +166,7 @@ private byte[] GetMessageBytes(string messageString, Encoding encoding = null)
}
byte[] messageBytes = Encoding.UTF8.GetBytes(messageString);
- byte[] headerBytes =
+ byte[] headerBytes =
Encoding.ASCII.GetBytes(
string.Format(
Constants.ContentLengthFormatString,
diff --git a/test/PowerShellEditorServices.Test/Console/ChoicePromptHandlerTests.cs b/test/PowerShellEditorServices.Test/Console/ChoicePromptHandlerTests.cs
index 684b39ca4..5034d5f94 100644
--- a/test/PowerShellEditorServices.Test/Console/ChoicePromptHandlerTests.cs
+++ b/test/PowerShellEditorServices.Test/Console/ChoicePromptHandlerTests.cs
@@ -7,6 +7,7 @@
using System.Threading;
using System.Threading.Tasks;
using Xunit;
+using Microsoft.PowerShell.EditorServices.Utility;
namespace Microsoft.PowerShell.EditorServices.Test.Console
{
@@ -70,7 +71,7 @@ public void ChoicePromptReturnsCorrectIdForHotKey()
[Fact]
public void ChoicePromptRepromptsOnInvalidInput()
{
- TestChoicePromptHandler choicePromptHandler =
+ TestChoicePromptHandler choicePromptHandler =
new TestChoicePromptHandler();
Task promptTask =
@@ -95,6 +96,10 @@ internal class TestChoicePromptHandler : ChoicePromptHandler
public int TimesPrompted { get; private set; }
+ public TestChoicePromptHandler() : base(new NullLogger())
+ {
+ }
+
public void ReturnInputString(string inputString)
{
this.linePromptTask.SetResult(inputString);
diff --git a/test/PowerShellEditorServices.Test/Console/ConsoleServiceTests.cs b/test/PowerShellEditorServices.Test/Console/ConsoleServiceTests.cs
index babd4e7c1..37356d5fc 100644
--- a/test/PowerShellEditorServices.Test/Console/ConsoleServiceTests.cs
+++ b/test/PowerShellEditorServices.Test/Console/ConsoleServiceTests.cs
@@ -49,7 +49,7 @@ public class ConsoleServiceTests : IDisposable
public ConsoleServiceTests()
{
- this.powerShellContext = new PowerShellContext();
+ this.powerShellContext = new PowerShellContext(new NullLogger());
ConsoleServicePSHost psHost =
new ConsoleServicePSHost(
powerShellContext,
@@ -560,7 +560,7 @@ internal class TestConsoleChoicePromptHandler : ConsoleChoicePromptHandler
public TestConsoleChoicePromptHandler(
IConsoleHost consoleHost,
TaskCompletionSource promptShownTask)
- : base(consoleHost)
+ : base(consoleHost, new NullLogger())
{
this.consoleHost = consoleHost;
this.promptShownTask = promptShownTask;
@@ -622,7 +622,7 @@ internal class TestConsoleInputPromptHandler : ConsoleInputPromptHandler
public TestConsoleInputPromptHandler(
IConsoleHost consoleHost,
TaskCompletionSource promptShownTask)
- : base(consoleHost)
+ : base(consoleHost, new NullLogger())
{
this.consoleHost = consoleHost;
this.promptShownTask = promptShownTask;
diff --git a/test/PowerShellEditorServices.Test/Console/InputPromptHandlerTests.cs b/test/PowerShellEditorServices.Test/Console/InputPromptHandlerTests.cs
index 50602aafb..1e2e1ad14 100644
--- a/test/PowerShellEditorServices.Test/Console/InputPromptHandlerTests.cs
+++ b/test/PowerShellEditorServices.Test/Console/InputPromptHandlerTests.cs
@@ -11,6 +11,7 @@
using System;
using System.Threading;
using System.Security;
+using Microsoft.PowerShell.EditorServices.Utility;
namespace Microsoft.PowerShell.EditorServices.Test.Console
{
@@ -131,6 +132,10 @@ internal class TestInputPromptHandler : InputPromptHandler
public Exception LastError { get; private set; }
+ public TestInputPromptHandler() : base(new NullLogger())
+ {
+ }
+
public void ReturnInputString(string inputString)
{
this.linePromptTask.SetResult(inputString);
diff --git a/test/PowerShellEditorServices.Test/Debugging/DebugServiceTests.cs b/test/PowerShellEditorServices.Test/Debugging/DebugServiceTests.cs
index 18bf1f8c4..7c3978722 100644
--- a/test/PowerShellEditorServices.Test/Debugging/DebugServiceTests.cs
+++ b/test/PowerShellEditorServices.Test/Debugging/DebugServiceTests.cs
@@ -31,10 +31,12 @@ public class DebugServiceTests : IDisposable
public DebugServiceTests()
{
- this.powerShellContext = PowerShellContextFactory.Create();
+ var logger = new NullLogger();
+
+ this.powerShellContext = PowerShellContextFactory.Create(logger);
this.powerShellContext.SessionStateChanged += powerShellContext_SessionStateChanged;
- this.workspace = new Workspace(this.powerShellContext.LocalPowerShellVersion.Version);
+ this.workspace = new Workspace(this.powerShellContext.LocalPowerShellVersion.Version, logger);
// Load the test debug file
this.debugScriptFile =
@@ -45,7 +47,7 @@ public DebugServiceTests()
this.workspace.GetFile(
@"..\..\..\..\PowerShellEditorServices.Test.Shared\Debugging\VariableTest.ps1");
- this.debugService = new DebugService(this.powerShellContext);
+ this.debugService = new DebugService(this.powerShellContext, logger);
this.debugService.DebuggerStopped += debugService_DebuggerStopped;
this.debugService.BreakpointUpdated += debugService_BreakpointUpdated;
this.runnerContext = SynchronizationContext.Current;
diff --git a/test/PowerShellEditorServices.Test/Extensions/ExtensionServiceTests.cs b/test/PowerShellEditorServices.Test/Extensions/ExtensionServiceTests.cs
index ecfe7f7be..1d6a6ef25 100644
--- a/test/PowerShellEditorServices.Test/Extensions/ExtensionServiceTests.cs
+++ b/test/PowerShellEditorServices.Test/Extensions/ExtensionServiceTests.cs
@@ -35,7 +35,8 @@ private enum EventType
public async Task InitializeAsync()
{
- this.powerShellContext = PowerShellContextFactory.Create();
+ var logger = new NullLogger();
+ this.powerShellContext = PowerShellContextFactory.Create(logger);
await this.powerShellContext.ImportCommandsModule(@"..\..\..\..\..\module\PowerShellEditorServices\Commands");
this.extensionService = new ExtensionService(this.powerShellContext);
diff --git a/test/PowerShellEditorServices.Test/Language/LanguageServiceTests.cs b/test/PowerShellEditorServices.Test/Language/LanguageServiceTests.cs
index c9be58fcb..4096ca6ad 100644
--- a/test/PowerShellEditorServices.Test/Language/LanguageServiceTests.cs
+++ b/test/PowerShellEditorServices.Test/Language/LanguageServiceTests.cs
@@ -15,6 +15,7 @@
using System.Linq;
using System.Threading.Tasks;
using Xunit;
+using Microsoft.PowerShell.EditorServices.Utility;
namespace Microsoft.PowerShell.EditorServices.Test.Language
{
@@ -25,12 +26,12 @@ public class LanguageServiceTests : IDisposable
private PowerShellContext powerShellContext;
private const string baseSharedScriptPath = @"..\..\..\..\PowerShellEditorServices.Test.Shared\";
-
public LanguageServiceTests()
{
- this.powerShellContext = PowerShellContextFactory.Create();
- this.workspace = new Workspace(this.powerShellContext.LocalPowerShellVersion.Version);
- this.languageService = new LanguageService(this.powerShellContext);
+ var logger = new NullLogger();
+ this.powerShellContext = PowerShellContextFactory.Create(logger);
+ this.workspace = new Workspace(this.powerShellContext.LocalPowerShellVersion.Version, logger);
+ this.languageService = new LanguageService(this.powerShellContext, logger);
}
public void Dispose()
@@ -163,7 +164,7 @@ public async Task LanguageServiceFindsFunctionDefinitionInWorkspace()
var definitionResult =
await this.GetDefinition(
FindsFunctionDefinitionInWorkspace.SourceDetails,
- new Workspace(this.powerShellContext.LocalPowerShellVersion.Version)
+ new Workspace(this.powerShellContext.LocalPowerShellVersion.Version, new NullLogger())
{
WorkspacePath = Path.Combine(baseSharedScriptPath, @"References")
});
diff --git a/test/PowerShellEditorServices.Test/PowerShellContextFactory.cs b/test/PowerShellEditorServices.Test/PowerShellContextFactory.cs
index 043585864..61d429a91 100644
--- a/test/PowerShellEditorServices.Test/PowerShellContextFactory.cs
+++ b/test/PowerShellEditorServices.Test/PowerShellContextFactory.cs
@@ -7,15 +7,16 @@
using Microsoft.PowerShell.EditorServices.Test.Console;
using System;
using System.IO;
+using Microsoft.PowerShell.EditorServices.Utility;
namespace Microsoft.PowerShell.EditorServices.Test
{
internal static class PowerShellContextFactory
{
- public static PowerShellContext Create()
+ public static PowerShellContext Create(ILogger logger)
{
- PowerShellContext powerShellContext = new PowerShellContext();
+ PowerShellContext powerShellContext = new PowerShellContext(logger);
powerShellContext.Initialize(
PowerShellContextTests.TestProfilePaths,
PowerShellContext.CreateRunspace(PowerShellContextTests.TestHostDetails, powerShellContext, false),
diff --git a/test/PowerShellEditorServices.Test/Session/PowerShellContextTests.cs b/test/PowerShellEditorServices.Test/Session/PowerShellContextTests.cs
index ff2001f6b..73ae260ab 100644
--- a/test/PowerShellEditorServices.Test/Session/PowerShellContextTests.cs
+++ b/test/PowerShellEditorServices.Test/Session/PowerShellContextTests.cs
@@ -42,7 +42,7 @@ public class PowerShellContextTests : IDisposable
public PowerShellContextTests()
{
- this.powerShellContext = PowerShellContextFactory.Create();
+ this.powerShellContext = PowerShellContextFactory.Create(new NullLogger());
this.powerShellContext.SessionStateChanged += OnSessionStateChanged;
this.stateChangeQueue = new AsyncQueue();
}
diff --git a/test/PowerShellEditorServices.Test/Session/WorkspaceTests.cs b/test/PowerShellEditorServices.Test/Session/WorkspaceTests.cs
index 16b58987f..4dfdabdc9 100644
--- a/test/PowerShellEditorServices.Test/Session/WorkspaceTests.cs
+++ b/test/PowerShellEditorServices.Test/Session/WorkspaceTests.cs
@@ -8,12 +8,13 @@
using System.IO;
using System.Linq;
using Xunit;
+using Microsoft.PowerShell.EditorServices.Utility;
namespace Microsoft.PowerShell.EditorServices.Test.Session
{
public class WorkspaceTests
{
- private static readonly Version PowerShellVersion = new Version("5.0");
+ private static readonly Version PowerShellVersion = new Version("5.0");
[Fact]
public void CanResolveWorkspaceRelativePath()
@@ -23,7 +24,7 @@ public void CanResolveWorkspaceRelativePath()
string testPathOutside = @"c:\Test\PeerPath\FilePath.ps1";
string testPathAnotherDrive = @"z:\TryAndFindMe\FilePath.ps1";
- Workspace workspace = new Workspace(PowerShellVersion);
+ Workspace workspace = new Workspace(PowerShellVersion, new NullLogger());
// Test without a workspace path
Assert.Equal(testPathOutside, workspace.GetRelativePath(testPathOutside));
diff --git a/test/PowerShellEditorServices.Test/Utility/LoggerTests.cs b/test/PowerShellEditorServices.Test/Utility/LoggerTests.cs
index bb667cbac..a343ad4a9 100644
--- a/test/PowerShellEditorServices.Test/Utility/LoggerTests.cs
+++ b/test/PowerShellEditorServices.Test/Utility/LoggerTests.cs
@@ -21,7 +21,7 @@ public class LoggerTests
AppContext.BaseDirectory,
#else
AppDomain.CurrentDomain.BaseDirectory,
-#endif
+#endif
"Test.log");
[Fact]
@@ -71,8 +71,11 @@ public void CanExcludeMessagesBelowErrorLevel()
private void AssertWritesMessageAtLevel(LogLevel logLevel)
{
// Write a message at the desired level
- Logger.Initialize(logFilePath, LogLevel.Verbose);
- Logger.Write(logLevel, testMessage);
+ var logger = new FileLogger(logFilePath, LogLevel.Verbose);
+ logger.Write(logLevel, testMessage);
+
+ // Dispose of the logger
+ logger.Dispose();
// Read the contents and verify that it's there
string logContents = this.ReadLogContents();
@@ -82,7 +85,7 @@ private void AssertWritesMessageAtLevel(LogLevel logLevel)
private void AssertExcludesMessageBelowLevel(LogLevel minimumLogLevel)
{
- Logger.Initialize(logFilePath, minimumLogLevel);
+ var logger = new FileLogger(logFilePath, minimumLogLevel);
// Get all possible log levels
LogLevel[] allLogLevels =
@@ -93,9 +96,12 @@ private void AssertExcludesMessageBelowLevel(LogLevel minimumLogLevel)
// Write a message at each log level
foreach (var logLevel in allLogLevels)
{
- Logger.Write((LogLevel)logLevel, testMessage);
+ logger.Write((LogLevel)logLevel, testMessage);
}
+ // Dispose of the logger
+ logger.Dispose();
+
// Make sure all excluded log levels aren't in the contents
string logContents = this.ReadLogContents();
for (int i = 0; i < (int)minimumLogLevel; i++)
@@ -122,6 +128,44 @@ private string ReadLogContents()
Encoding.UTF8));
}
+ private class LogPathHelper : IDisposable
+ {
+ private readonly string logFilePathTemplate =
+ Path.Combine(
+ #if CoreCLR
+ AppContext.BaseDirectory,
+ #else
+ AppDomain.CurrentDomain.BaseDirectory,
+ #endif
+ "Test-{0}.log");
+
+ public string LogFilePath { get; private set; }
+
+ public LogPathHelper()
+ {
+ this.LogFilePath =
+ string.Format(
+ logFilePathTemplate,
+ "2");
+ //Guid.NewGuid().ToString());
+ }
+
+ public void Dispose()
+ {
+ // Delete the created file
+ try
+ {
+ if (this.LogFilePath != null)
+ {
+ File.Delete(this.LogFilePath);
+ }
+ }
+ catch (Exception)
+ {
+ }
+ }
+ }
+
#endregion
}
}