diff --git a/src/Microsoft.AspNetCore.Razor.Design/build/netstandard2.0/Microsoft.AspNetCore.Razor.Design.CodeGeneration.targets b/src/Microsoft.AspNetCore.Razor.Design/build/netstandard2.0/Microsoft.AspNetCore.Razor.Design.CodeGeneration.targets
index 09ffa3e51a..699b4608f3 100644
--- a/src/Microsoft.AspNetCore.Razor.Design/build/netstandard2.0/Microsoft.AspNetCore.Razor.Design.CodeGeneration.targets
+++ b/src/Microsoft.AspNetCore.Razor.Design/build/netstandard2.0/Microsoft.AspNetCore.Razor.Design.CodeGeneration.targets
@@ -71,6 +71,7 @@
DebugTool="$(_RazorDebugTagHelperTool)"
ToolAssembly="$(_RazorToolAssembly)"
UseServer="$(UseRazorBuildServer)"
+ ForceServer="$(_RazorForceBuildServer)"
PipeName="$(_RazorBuildServerPipeName)"
Assemblies="@(RazorReferencePath)"
ProjectRoot="$(MSBuildProjectDirectory)"
@@ -118,6 +119,7 @@
DebugTool="$(_RazorDebugGenerateCodeTool)"
ToolAssembly="$(_RazorToolAssembly)"
UseServer="$(UseRazorBuildServer)"
+ ForceServer="$(_RazorForceBuildServer)"
PipeName="$(_RazorBuildServerPipeName)"
Sources="@(RazorGenerateWithTargetPath)"
ProjectRoot="$(MSBuildProjectDirectory)"
diff --git a/src/Microsoft.AspNetCore.Razor.Tasks/DotnetToolTask.cs b/src/Microsoft.AspNetCore.Razor.Tasks/DotnetToolTask.cs
index 5b28b3eca9..2539d3e5ed 100644
--- a/src/Microsoft.AspNetCore.Razor.Tasks/DotnetToolTask.cs
+++ b/src/Microsoft.AspNetCore.Razor.Tasks/DotnetToolTask.cs
@@ -5,14 +5,11 @@ using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
-using System.Linq;
using System.Threading;
using Microsoft.AspNetCore.Razor.Tools;
using Microsoft.Build.Framework;
using Microsoft.Build.Utilities;
-using Microsoft.CodeAnalysis.CommandLine;
using Microsoft.Extensions.CommandLineUtils;
-using Roslyn.Utilities;
namespace Microsoft.AspNetCore.Razor.Tasks
{
@@ -29,6 +26,9 @@ namespace Microsoft.AspNetCore.Razor.Tasks
public bool UseServer { get; set; }
+ // Specifies whether we should fallback to in-process execution if server execution fails.
+ public bool ForceServer { get; set; }
+
public string PipeName { get; set; }
protected override string ToolName => "dotnet";
@@ -115,11 +115,11 @@ namespace Microsoft.AspNetCore.Razor.Tasks
string commandLineCommands,
out int result)
{
- CompilerServerLogger.Log("Server execution started.");
+ Log.LogMessage(StandardOutputLoggingImportance, "Server execution started.");
using (_razorServerCts = new CancellationTokenSource())
{
- CompilerServerLogger.Log($"CommandLine = '{commandLineCommands}'");
- CompilerServerLogger.Log($"ServerResponseFile = '{responseFileCommands}'");
+ Log.LogMessage(StandardOutputLoggingImportance, $"CommandLine = '{commandLineCommands}'");
+ Log.LogMessage(StandardOutputLoggingImportance, $"ServerResponseFile = '{responseFileCommands}'");
// The server contains the tools for discovering tag helpers and generating Razor code.
var clientDir = Path.GetDirectoryName(ToolAssembly);
@@ -141,14 +141,35 @@ namespace Microsoft.AspNetCore.Razor.Tasks
{
result = completedResponse.ReturnCode;
- CompilerServerLogger.Log($"Server execution completed with return code {result}.");
+ if (result == 0)
+ {
+ Log.LogMessage(StandardOutputLoggingImportance, $"Server execution completed with return code {result}.");
+ return true;
+ }
+ else
+ {
+ Log.LogMessage(
+ StandardOutputLoggingImportance,
+ $"Server execution completed with return code {result}. For more info, check the server log file in the location specified by the RAZORBUILDSERVER_LOG environment variable.");
+ }
+ }
+ else
+ {
+ Log.LogMessage(
+ StandardOutputLoggingImportance,
+ $"Server execution failed with response {response.Type}. For more info, check the server log file in the location specified by the RAZORBUILDSERVER_LOG environment variable.");
+ }
+ result = -1;
+
+ if (ForceServer)
+ {
+ // We don't want to fallback to in-process execution.
return true;
}
- }
- CompilerServerLogger.Log("Server execution failed.");
- result = -1;
+ Log.LogMessage(StandardOutputLoggingImportance, "Fallback to in-process execution.");
+ }
return false;
}
diff --git a/src/Microsoft.AspNetCore.Razor.Tasks/Microsoft.AspNetCore.Razor.Tasks.csproj b/src/Microsoft.AspNetCore.Razor.Tasks/Microsoft.AspNetCore.Razor.Tasks.csproj
index b868310b42..79eefc909b 100644
--- a/src/Microsoft.AspNetCore.Razor.Tasks/Microsoft.AspNetCore.Razor.Tasks.csproj
+++ b/src/Microsoft.AspNetCore.Razor.Tasks/Microsoft.AspNetCore.Razor.Tasks.csproj
@@ -16,12 +16,6 @@
-
- Shared\CompilerServerLogger.cs
-
-
- Shared\PlatformInformation.cs
-
Shared\ServerProtocol\%(FileName)
diff --git a/src/Microsoft.AspNetCore.Razor.Tools/Client.cs b/src/Microsoft.AspNetCore.Razor.Tools/Client.cs
index 9a0334b8db..4f7903dec5 100644
--- a/src/Microsoft.AspNetCore.Razor.Tools/Client.cs
+++ b/src/Microsoft.AspNetCore.Razor.Tools/Client.cs
@@ -6,7 +6,6 @@ using System.IO;
using System.IO.Pipes;
using System.Threading;
using System.Threading.Tasks;
-using Microsoft.CodeAnalysis.CommandLine;
namespace Microsoft.AspNetCore.Razor.Tools
{
@@ -39,12 +38,12 @@ namespace Microsoft.AspNetCore.Razor.Tools
// Machine-local named pipes are named "\\.\pipe\".
// We use the SHA1 of the directory the compiler exes live in as the pipe name.
// The NamedPipeClientStream class handles the "\\.\pipe\" part for us.
- CompilerServerLogger.Log("Attempt to open named pipe '{0}'", pipeName);
+ ServerLogger.Log("Attempt to open named pipe '{0}'", pipeName);
var stream = new NamedPipeClientStream(".", pipeName, PipeDirection.InOut, PipeOptions.Asynchronous);
cancellationToken.ThrowIfCancellationRequested();
- CompilerServerLogger.Log("Attempt to connect named pipe '{0}'", pipeName);
+ ServerLogger.Log("Attempt to connect named pipe '{0}'", pipeName);
try
{
await stream.ConnectAsync(timeoutMilliseconds, cancellationToken);
@@ -55,11 +54,11 @@ namespace Microsoft.AspNetCore.Razor.Tools
// From docs:
// - TimeoutException: Could not connect to the server within the specified timeout period.
// - IOException: The server is connected to another client and the time-out period has expired.
- CompilerServerLogger.Log($"Connecting to server timed out after {timeoutMilliseconds} ms");
+ ServerLogger.Log($"Connecting to server timed out after {timeoutMilliseconds} ms");
return null;
}
- CompilerServerLogger.Log("Named pipe '{0}' connected", pipeName);
+ ServerLogger.Log("Named pipe '{0}' connected", pipeName);
cancellationToken.ThrowIfCancellationRequested();
// The original code in Roslyn checks that the server pipe is owned by the same user for security.
@@ -70,7 +69,7 @@ namespace Microsoft.AspNetCore.Razor.Tools
}
catch (Exception e) when (!(e is TaskCanceledException || e is OperationCanceledException))
{
- CompilerServerLogger.LogException(e, "Exception while connecting to process");
+ ServerLogger.LogException(e, "Exception while connecting to process");
return null;
}
}
@@ -108,9 +107,9 @@ namespace Microsoft.AspNetCore.Razor.Tools
try
{
- CompilerServerLogger.Log($"Before poking pipe {Identifier}.");
+ ServerLogger.Log($"Before poking pipe {Identifier}.");
await Stream.ReadAsync(Array.Empty(), 0, 0, cancellationToken);
- CompilerServerLogger.Log($"After poking pipe {Identifier}.");
+ ServerLogger.Log($"After poking pipe {Identifier}.");
}
catch (OperationCanceledException)
{
@@ -119,7 +118,7 @@ namespace Microsoft.AspNetCore.Razor.Tools
{
// It is okay for this call to fail. Errors will be reflected in the
// IsConnected property which will be read on the next iteration.
- CompilerServerLogger.LogException(e, $"Error poking pipe {Identifier}.");
+ ServerLogger.LogException(e, $"Error poking pipe {Identifier}.");
}
}
}
diff --git a/src/Microsoft.AspNetCore.Razor.Tools/CompilerHost.cs b/src/Microsoft.AspNetCore.Razor.Tools/CompilerHost.cs
index a00ad04aa4..c4b96df6b2 100644
--- a/src/Microsoft.AspNetCore.Razor.Tools/CompilerHost.cs
+++ b/src/Microsoft.AspNetCore.Razor.Tools/CompilerHost.cs
@@ -2,9 +2,9 @@
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System.Collections.Generic;
+using System.IO;
using System.Linq;
using System.Threading;
-using Microsoft.CodeAnalysis.CommandLine;
namespace Microsoft.AspNetCore.Razor.Tools
{
@@ -26,13 +26,33 @@ namespace Microsoft.AspNetCore.Razor.Tools
return new RejectedServerResponse();
}
+ var exitCode = 0;
+ var output = string.Empty;
var app = new Application(cancellationToken);
var commandArgs = parsed.args.ToArray();
- var exitCode = app.Execute(commandArgs);
- var output = app.Out.ToString() ?? string.Empty;
+ if (ServerLogger.IsLoggingEnabled)
+ {
+ using (var writer = new StringWriter())
+ {
+ app.Out = writer;
+ app.Error = writer;
+ exitCode = app.Execute(commandArgs);
+ output = writer.ToString();
+ ServerLogger.Log(output);
+ }
+ }
+ else
+ {
+ using (var writer = new StreamWriter(Stream.Null))
+ {
+ app.Out = writer;
+ app.Error = writer;
+ exitCode = app.Execute(commandArgs);
+ }
+ }
- return new CompletedServerResponse(exitCode, utf8output: false, output: output);
+ return new CompletedServerResponse(exitCode, utf8output: false, output: string.Empty);
}
private bool TryParseArguments(ServerRequest request, out (string workingDirectory, string tempDirectory, string[] args) parsed)
@@ -59,16 +79,16 @@ namespace Microsoft.AspNetCore.Razor.Tools
}
}
- CompilerServerLogger.Log($"WorkingDirectory = '{workingDirectory}'");
- CompilerServerLogger.Log($"TempDirectory = '{tempDirectory}'");
+ ServerLogger.Log($"WorkingDirectory = '{workingDirectory}'");
+ ServerLogger.Log($"TempDirectory = '{tempDirectory}'");
for (var i = 0; i < args.Count; i++)
{
- CompilerServerLogger.Log($"Argument[{i}] = '{request.Arguments[i]}'");
+ ServerLogger.Log($"Argument[{i}] = '{request.Arguments[i]}'");
}
if (string.IsNullOrEmpty(workingDirectory))
{
- CompilerServerLogger.Log($"Rejecting build due to missing working directory");
+ ServerLogger.Log($"Rejecting build due to missing working directory");
parsed = default;
return false;
@@ -76,7 +96,7 @@ namespace Microsoft.AspNetCore.Razor.Tools
if (string.IsNullOrEmpty(tempDirectory))
{
- CompilerServerLogger.Log($"Rejecting build due to missing temp directory");
+ ServerLogger.Log($"Rejecting build due to missing temp directory");
parsed = default;
return false;
@@ -84,7 +104,7 @@ namespace Microsoft.AspNetCore.Razor.Tools
if (string.IsNullOrEmpty(tempDirectory))
{
- CompilerServerLogger.Log($"Rejecting build due to missing temp directory");
+ ServerLogger.Log($"Rejecting build due to missing temp directory");
parsed = default;
return false;
diff --git a/src/Microsoft.AspNetCore.Razor.Tools/ConnectionHost.cs b/src/Microsoft.AspNetCore.Razor.Tools/ConnectionHost.cs
index 7da0a05497..6bda4338a8 100644
--- a/src/Microsoft.AspNetCore.Razor.Tools/ConnectionHost.cs
+++ b/src/Microsoft.AspNetCore.Razor.Tools/ConnectionHost.cs
@@ -6,7 +6,6 @@ using System.IO;
using System.IO.Pipes;
using System.Threading;
using System.Threading.Tasks;
-using Microsoft.CodeAnalysis.CommandLine;
namespace Microsoft.AspNetCore.Razor.Tools
{
@@ -58,13 +57,13 @@ namespace Microsoft.AspNetCore.Razor.Tools
PipeBufferSize, // Default input buffer
PipeBufferSize);// Default output buffer
- CompilerServerLogger.Log("Waiting for new connection");
+ ServerLogger.Log("Waiting for new connection");
await pipeStream.WaitForConnectionAsync(cancellationToken);
- CompilerServerLogger.Log("Pipe connection detected.");
+ ServerLogger.Log("Pipe connection detected.");
if (Environment.Is64BitProcess || Memory.IsMemoryAvailable())
{
- CompilerServerLogger.Log("Memory available - accepting connection");
+ ServerLogger.Log("Memory available - accepting connection");
return new NamedPipeConnection(pipeStream, GetNextIdentifier());
}
@@ -96,9 +95,9 @@ namespace Microsoft.AspNetCore.Razor.Tools
try
{
- CompilerServerLogger.Log($"Before poking pipe {Identifier}.");
+ ServerLogger.Log($"Before poking pipe {Identifier}.");
await Stream.ReadAsync(Array.Empty(), 0, 0, cancellationToken);
- CompilerServerLogger.Log($"After poking pipe {Identifier}.");
+ ServerLogger.Log($"After poking pipe {Identifier}.");
}
catch (OperationCanceledException)
{
@@ -107,14 +106,14 @@ namespace Microsoft.AspNetCore.Razor.Tools
{
// It is okay for this call to fail. Errors will be reflected in the
// IsConnected property which will be read on the next iteration.
- CompilerServerLogger.LogException(e, $"Error poking pipe {Identifier}.");
+ ServerLogger.LogException(e, $"Error poking pipe {Identifier}.");
}
}
}
protected override void Dispose(bool disposing)
{
- CompilerServerLogger.Log($"Pipe {Identifier}: Closing.");
+ ServerLogger.Log($"Pipe {Identifier}: Closing.");
try
{
@@ -126,7 +125,7 @@ namespace Microsoft.AspNetCore.Razor.Tools
// for which we can no longer communicate and that's okay because the Close method indicates we are
// done with the client already.
var message = string.Format($"Pipe {Identifier}: Error closing pipe.");
- CompilerServerLogger.LogException(ex, message);
+ ServerLogger.LogException(ex, message);
}
}
}
diff --git a/src/Microsoft.AspNetCore.Razor.Tools/DefaultRequestDispatcher.cs b/src/Microsoft.AspNetCore.Razor.Tools/DefaultRequestDispatcher.cs
index 7725a9b3cb..26747a06b6 100644
--- a/src/Microsoft.AspNetCore.Razor.Tools/DefaultRequestDispatcher.cs
+++ b/src/Microsoft.AspNetCore.Razor.Tools/DefaultRequestDispatcher.cs
@@ -8,7 +8,6 @@ using System.Linq;
using System.Runtime;
using System.Threading;
using System.Threading.Tasks;
-using Microsoft.CodeAnalysis.CommandLine;
namespace Microsoft.AspNetCore.Razor.Tools
{
@@ -318,7 +317,7 @@ namespace Microsoft.AspNetCore.Razor.Tools
{
// Unable to establish a connection with the client. The client is responsible for
// handling this case. Nothing else for us to do here.
- CompilerServerLogger.LogException(ex, "Error creating client named pipe");
+ ServerLogger.LogException(ex, "Error creating client named pipe");
return new ConnectionResult(ConnectionResult.Reason.CompilationNotStarted);
}
@@ -329,13 +328,13 @@ namespace Microsoft.AspNetCore.Razor.Tools
ServerRequest request;
try
{
- CompilerServerLogger.Log("Begin reading request.");
+ ServerLogger.Log("Begin reading request.");
request = await ServerRequest.ReadAsync(connection.Stream, cancellationToken).ConfigureAwait(false);
- CompilerServerLogger.Log("End reading request.");
+ ServerLogger.Log("End reading request.");
}
catch (Exception e)
{
- CompilerServerLogger.LogException(e, "Error reading build request.");
+ ServerLogger.LogException(e, "Error reading build request.");
return new ConnectionResult(ConnectionResult.Reason.CompilationNotStarted);
}
@@ -379,9 +378,9 @@ namespace Microsoft.AspNetCore.Razor.Tools
try
{
- CompilerServerLogger.Log("Begin writing response.");
+ ServerLogger.Log("Begin writing response.");
await response.WriteAsync(connection.Stream, cancellationToken);
- CompilerServerLogger.Log("End writing response.");
+ ServerLogger.Log("End writing response.");
reason = ConnectionResult.Reason.CompilationCompleted;
}
@@ -405,7 +404,7 @@ namespace Microsoft.AspNetCore.Razor.Tools
}
catch (Exception ex)
{
- CompilerServerLogger.LogException(ex, "Error handling connection");
+ ServerLogger.LogException(ex, "Error handling connection");
return new ConnectionResult(ConnectionResult.Reason.ClientException);
}
}
@@ -414,11 +413,11 @@ namespace Microsoft.AspNetCore.Razor.Tools
{
Func func = () =>
{
- CompilerServerLogger.Log("Begin processing request");
+ ServerLogger.Log("Begin processing request");
var response = _compilerHost.Execute(buildRequest, cancellationToken);
- CompilerServerLogger.Log("End processing request");
+ ServerLogger.Log("End processing request");
return response;
};
diff --git a/src/Microsoft.AspNetCore.Razor.Tools/Roslyn/PlatformInformation.cs b/src/Microsoft.AspNetCore.Razor.Tools/Roslyn/PlatformInformation.cs
deleted file mode 100644
index 476ee889ff..0000000000
--- a/src/Microsoft.AspNetCore.Razor.Tools/Roslyn/PlatformInformation.cs
+++ /dev/null
@@ -1,17 +0,0 @@
-// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
-
-using System.IO;
-
-namespace Roslyn.Utilities
-{
- ///
- /// This class provides simple properties for determining whether the current platform is Windows or Unix-based.
- /// We intentionally do not use System.Runtime.InteropServices.RuntimeInformation.IsOSPlatform(...) because
- /// it incorrectly reports 'true' for 'Windows' in desktop builds running on Unix-based platforms via Mono.
- ///
- internal static class PlatformInformation
- {
- public static bool IsWindows => Path.DirectorySeparatorChar == '\\';
- public static bool IsUnix => Path.DirectorySeparatorChar == '/';
- }
-}
\ No newline at end of file
diff --git a/src/Microsoft.AspNetCore.Razor.Tools/ServerProtocol/ServerConnection.cs b/src/Microsoft.AspNetCore.Razor.Tools/ServerProtocol/ServerConnection.cs
index 6c27dd2d50..3f729da331 100644
--- a/src/Microsoft.AspNetCore.Razor.Tools/ServerProtocol/ServerConnection.cs
+++ b/src/Microsoft.AspNetCore.Razor.Tools/ServerProtocol/ServerConnection.cs
@@ -8,8 +8,6 @@ using System.Runtime.InteropServices;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
-using Roslyn.Utilities;
-using static Microsoft.CodeAnalysis.CommandLine.CompilerServerLogger;
namespace Microsoft.AspNetCore.Razor.Tools
{
@@ -204,26 +202,26 @@ namespace Microsoft.AspNetCore.Razor.Tools
// Write the request
try
{
- Log("Begin writing request");
+ ServerLogger.Log("Begin writing request");
await request.WriteAsync(client.Stream, cancellationToken).ConfigureAwait(false);
- Log("End writing request");
+ ServerLogger.Log("End writing request");
}
catch (Exception e)
{
- LogException(e, "Error writing build request.");
+ ServerLogger.LogException(e, "Error writing build request.");
return new RejectedServerResponse();
}
// Wait for the compilation and a monitor to detect if the server disconnects
var serverCts = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken);
- Log("Begin reading response");
+ ServerLogger.Log("Begin reading response");
var responseTask = ServerResponse.ReadAsync(client.Stream, serverCts.Token);
var monitorTask = client.WaitForDisconnectAsync(serverCts.Token);
await Task.WhenAny(responseTask, monitorTask).ConfigureAwait(false);
- Log("End reading response");
+ ServerLogger.Log("End reading response");
if (responseTask.IsCompleted)
{
@@ -234,13 +232,13 @@ namespace Microsoft.AspNetCore.Razor.Tools
}
catch (Exception e)
{
- LogException(e, "Error reading response");
+ ServerLogger.LogException(e, "Error reading response");
response = new RejectedServerResponse();
}
}
else
{
- Log("Server disconnect");
+ ServerLogger.Log("Server disconnect");
response = new RejectedServerResponse();
}
@@ -282,7 +280,7 @@ namespace Microsoft.AspNetCore.Razor.Tools
startInfo.dwFlags = NativeMethods.STARTF_USESTDHANDLES;
var dwCreationFlags = NativeMethods.NORMAL_PRIORITY_CLASS | NativeMethods.CREATE_NO_WINDOW;
- Log("Attempting to create process '{0}'", expectedPath);
+ ServerLogger.Log("Attempting to create process '{0}'", expectedPath);
var builder = new StringBuilder($@"""{expectedPath}"" {processArguments}");
@@ -300,13 +298,13 @@ namespace Microsoft.AspNetCore.Razor.Tools
if (success)
{
- Log("Successfully created process with process id {0}", processInfo.dwProcessId);
+ ServerLogger.Log("Successfully created process with process id {0}", processInfo.dwProcessId);
NativeMethods.CloseHandle(processInfo.hProcess);
NativeMethods.CloseHandle(processInfo.hThread);
}
else
{
- Log("Failed to create process. GetLastError={0}", Marshal.GetLastWin32Error());
+ ServerLogger.Log("Failed to create process. GetLastError={0}", Marshal.GetLastWin32Error());
}
return success;
}
@@ -336,4 +334,15 @@ namespace Microsoft.AspNetCore.Razor.Tools
}
}
}
+
+ ///
+ /// This class provides simple properties for determining whether the current platform is Windows or Unix-based.
+ /// We intentionally do not use System.Runtime.InteropServices.RuntimeInformation.IsOSPlatform(...) because
+ /// it incorrectly reports 'true' for 'Windows' in desktop builds running on Unix-based platforms via Mono.
+ ///
+ internal static class PlatformInformation
+ {
+ public static bool IsWindows => Path.DirectorySeparatorChar == '\\';
+ public static bool IsUnix => Path.DirectorySeparatorChar == '/';
+ }
}
\ No newline at end of file
diff --git a/src/Microsoft.AspNetCore.Razor.Tools/Roslyn/CompilerServerLogger.cs b/src/Microsoft.AspNetCore.Razor.Tools/ServerProtocol/ServerLogger.cs
similarity index 84%
rename from src/Microsoft.AspNetCore.Razor.Tools/Roslyn/CompilerServerLogger.cs
rename to src/Microsoft.AspNetCore.Razor.Tools/ServerProtocol/ServerLogger.cs
index c2c95f00bf..21ff3a06a9 100644
--- a/src/Microsoft.AspNetCore.Razor.Tools/Roslyn/CompilerServerLogger.cs
+++ b/src/Microsoft.AspNetCore.Razor.Tools/ServerProtocol/ServerLogger.cs
@@ -1,25 +1,22 @@
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
-using Roslyn.Utilities;
using System;
-using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
-using System.Linq;
using System.Text;
using System.Threading;
-namespace Microsoft.CodeAnalysis.CommandLine
+namespace Microsoft.AspNetCore.Razor.Tools
{
///
/// Class for logging information about what happens in the server and client parts of the
- /// Roslyn command line compiler and build tasks. Useful for debugging what is going on.
+ /// Razor command line compiler and build tasks. Useful for debugging what is going on.
///
///
- /// To use the logging, set the environment variable RoslynCommandLineLogFile to the name
+ /// To use the logging, set the environment variable RAZORBUILDSERVER_LOG to the name
/// of a file to log to. This file is logged to by both client and server components.
///
- internal class CompilerServerLogger
+ internal class ServerLogger
{
// Environment variable, if set, to enable logging and set the file to log to.
private const string EnvironmentVariable = "RAZORBUILDSERVER_LOG";
@@ -30,17 +27,19 @@ namespace Microsoft.CodeAnalysis.CommandLine
///
/// Static class initializer that initializes logging.
///
- static CompilerServerLogger()
+ static ServerLogger()
{
s_loggingStream = null;
try
{
// Check if the environment
- string loggingFileName = Environment.GetEnvironmentVariable(EnvironmentVariable);
+ var loggingFileName = Environment.GetEnvironmentVariable(EnvironmentVariable);
if (loggingFileName != null)
{
+ IsLoggingEnabled = true;
+
// If the environment variable contains the path of a currently existing directory,
// then use a process-specific name for the log file and put it in that directory.
// Otherwise, assume that the environment variable specifies the name of the log file.
@@ -59,6 +58,8 @@ namespace Microsoft.CodeAnalysis.CommandLine
}
}
+ public static bool IsLoggingEnabled { get; }
+
///
/// Set the logging prefix that describes our role.
/// Typically a 3-letter abbreviation. If logging happens before this, it's logged with "---".
@@ -73,11 +74,11 @@ namespace Microsoft.CodeAnalysis.CommandLine
///
public static void LogException(Exception e, string reason)
{
- if (s_loggingStream != null)
+ if (IsLoggingEnabled)
{
Log("Exception '{0}' occurred during '{1}'. Stack trace:\r\n{2}", e.Message, reason, e.StackTrace);
- int innerExceptionLevel = 0;
+ var innerExceptionLevel = 0;
e = e.InnerException;
while (e != null)
@@ -94,7 +95,7 @@ namespace Microsoft.CodeAnalysis.CommandLine
///
public static void Log(string format, params object[] arguments)
{
- if (s_loggingStream != null)
+ if (IsLoggingEnabled)
{
Log(string.Format(format, arguments));
}
@@ -106,12 +107,12 @@ namespace Microsoft.CodeAnalysis.CommandLine
///
public static void Log(string message)
{
- if (s_loggingStream != null)
+ if (IsLoggingEnabled)
{
- string prefix = GetLoggingPrefix();
+ var prefix = GetLoggingPrefix();
- string output = prefix + message + "\r\n";
- byte[] bytes = Encoding.UTF8.GetBytes(output);
+ var output = prefix + message + "\r\n";
+ var bytes = Encoding.UTF8.GetBytes(output);
// Because multiple processes might be logging to the same file, we always seek to the end,
// write, and flush.
diff --git a/src/Microsoft.AspNetCore.Razor.Tools/ServerProtocol/ServerProtocol.cs b/src/Microsoft.AspNetCore.Razor.Tools/ServerProtocol/ServerProtocol.cs
index 807690d7f4..940dda2845 100644
--- a/src/Microsoft.AspNetCore.Razor.Tools/ServerProtocol/ServerProtocol.cs
+++ b/src/Microsoft.AspNetCore.Razor.Tools/ServerProtocol/ServerProtocol.cs
@@ -4,7 +4,6 @@
using System.IO;
using System.Threading;
using System.Threading.Tasks;
-using Microsoft.CodeAnalysis.CommandLine;
namespace Microsoft.AspNetCore.Razor.Tools
{
@@ -49,7 +48,7 @@ namespace Microsoft.AspNetCore.Razor.Tools
var totalBytesRead = 0;
do
{
- CompilerServerLogger.Log("Attempting to read {0} bytes from the stream", count - totalBytesRead);
+ ServerLogger.Log("Attempting to read {0} bytes from the stream", count - totalBytesRead);
var bytesRead = await stream.ReadAsync(
buffer,
totalBytesRead,
@@ -59,13 +58,13 @@ namespace Microsoft.AspNetCore.Razor.Tools
if (bytesRead == 0)
{
- CompilerServerLogger.Log("Unexpected -- read 0 bytes from the stream.");
+ ServerLogger.Log("Unexpected -- read 0 bytes from the stream.");
throw new EndOfStreamException("Reached end of stream before end of read.");
}
- CompilerServerLogger.Log("Read {0} bytes", bytesRead);
+ ServerLogger.Log("Read {0} bytes", bytesRead);
totalBytesRead += bytesRead;
} while (totalBytesRead < count);
- CompilerServerLogger.Log("Finished read");
+ ServerLogger.Log("Finished read");
}
}
}
diff --git a/src/Microsoft.AspNetCore.Razor.Tools/ServerProtocol/ServerRequest.cs b/src/Microsoft.AspNetCore.Razor.Tools/ServerProtocol/ServerRequest.cs
index 5fa861717c..e1dd9308b0 100644
--- a/src/Microsoft.AspNetCore.Razor.Tools/ServerProtocol/ServerRequest.cs
+++ b/src/Microsoft.AspNetCore.Razor.Tools/ServerProtocol/ServerRequest.cs
@@ -9,7 +9,6 @@ using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
-using static Microsoft.CodeAnalysis.CommandLine.CompilerServerLogger;
// After the server pipe is connected, it forks off a thread to handle the connection, and creates
// a new instance of the pipe to listen for new clients. When it gets a request, it validates
@@ -84,9 +83,9 @@ namespace Microsoft.AspNetCore.Razor.Tools
IList args,
string keepAlive = null)
{
- Log("Creating ServerRequest");
- Log($"Working directory: {workingDirectory}");
- Log($"Temp directory: {tempDirectory}");
+ ServerLogger.Log("Creating ServerRequest");
+ ServerLogger.Log($"Working directory: {workingDirectory}");
+ ServerLogger.Log($"Temp directory: {tempDirectory}");
var requestLength = args.Count + 1;
var requestArgs = new List(requestLength)
@@ -103,7 +102,7 @@ namespace Microsoft.AspNetCore.Razor.Tools
for (var i = 0; i < args.Count; ++i)
{
var arg = args[i];
- Log($"argument[{i}] = {arg}");
+ ServerLogger.Log($"argument[{i}] = {arg}");
requestArgs.Add(new RequestArgument(RequestArgument.ArgumentId.CommandLineArgument, i, arg));
}
@@ -130,14 +129,14 @@ namespace Microsoft.AspNetCore.Razor.Tools
{
// Read the length of the request
var lengthBuffer = new byte[4];
- Log("Reading length of request");
+ ServerLogger.Log("Reading length of request");
await ServerProtocol.ReadAllAsync(inStream, lengthBuffer, 4, cancellationToken).ConfigureAwait(false);
var length = BitConverter.ToInt32(lengthBuffer, 0);
// Back out if the request is > 1MB
if (length > 0x100000)
{
- Log("Request is over 1MB in length, cancelling read.");
+ ServerLogger.Log("Request is over 1MB in length, cancelling read.");
return null;
}
@@ -149,7 +148,7 @@ namespace Microsoft.AspNetCore.Razor.Tools
cancellationToken.ThrowIfCancellationRequested();
- Log("Parsing request");
+ ServerLogger.Log("Parsing request");
// Parse the request into the Request data structure.
using (var reader = new BinaryReader(new MemoryStream(requestBuffer), Encoding.Unicode))
{
@@ -177,7 +176,7 @@ namespace Microsoft.AspNetCore.Razor.Tools
using (var writer = new BinaryWriter(memoryStream, Encoding.Unicode))
{
// Format the request.
- Log("Formatting request");
+ ServerLogger.Log("Formatting request");
writer.Write(ProtocolVersion);
writer.Write(Arguments.Count);
foreach (var arg in Arguments)
@@ -195,17 +194,17 @@ namespace Microsoft.AspNetCore.Razor.Tools
// Back out if the request is > 1 MB
if (memoryStream.Length > 0x100000)
{
- Log("Request is over 1MB in length, cancelling write");
+ ServerLogger.Log("Request is over 1MB in length, cancelling write");
throw new ArgumentOutOfRangeException();
}
// Send the request to the server
- Log("Writing length of request.");
+ ServerLogger.Log("Writing length of request.");
await outStream
.WriteAsync(BitConverter.GetBytes(length), 0, 4, cancellationToken)
.ConfigureAwait(false);
- Log("Writing request of size {0}", length);
+ ServerLogger.Log("Writing request of size {0}", length);
// Write the request
memoryStream.Position = 0;
await memoryStream
diff --git a/src/Microsoft.AspNetCore.Razor.Tools/ServerProtocol/ServerResponse.cs b/src/Microsoft.AspNetCore.Razor.Tools/ServerProtocol/ServerResponse.cs
index ea2c32ce44..66eb1e63f3 100644
--- a/src/Microsoft.AspNetCore.Razor.Tools/ServerProtocol/ServerResponse.cs
+++ b/src/Microsoft.AspNetCore.Razor.Tools/ServerProtocol/ServerResponse.cs
@@ -6,7 +6,6 @@ using System.IO;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
-using static Microsoft.CodeAnalysis.CommandLine.CompilerServerLogger;
// After the server pipe is connected, it forks off a thread to handle the connection, and creates
// a new instance of the pipe to listen for new clients. When it gets a request, it validates
@@ -55,7 +54,7 @@ namespace Microsoft.AspNetCore.Razor.Tools
using (var writer = new BinaryWriter(memoryStream, Encoding.Unicode))
{
// Format the response
- Log("Formatting Response");
+ ServerLogger.Log("Formatting Response");
writer.Write((int)Type);
AddResponseBody(writer);
@@ -68,7 +67,7 @@ namespace Microsoft.AspNetCore.Razor.Tools
// Write the length of the response
var length = checked((int)memoryStream.Length);
- Log("Writing response length");
+ ServerLogger.Log("Writing response length");
// There is no way to know the number of bytes written to
// the pipe stream. We just have to assume all of them are written.
await outStream
@@ -76,7 +75,7 @@ namespace Microsoft.AspNetCore.Razor.Tools
.ConfigureAwait(false);
// Write the response
- Log("Writing response of size {0}", length);
+ ServerLogger.Log("Writing response of size {0}", length);
memoryStream.Position = 0;
await memoryStream
.CopyToAsync(outStream, bufferSize: length, cancellationToken: cancellationToken)
@@ -94,14 +93,14 @@ namespace Microsoft.AspNetCore.Razor.Tools
///
public static async Task ReadAsync(Stream stream, CancellationToken cancellationToken = default(CancellationToken))
{
- Log("Reading response length");
+ ServerLogger.Log("Reading response length");
// Read the response length
var lengthBuffer = new byte[4];
await ServerProtocol.ReadAllAsync(stream, lengthBuffer, 4, cancellationToken).ConfigureAwait(false);
var length = BitConverter.ToUInt32(lengthBuffer, 0);
// Read the response
- Log("Reading response of length {0}", length);
+ ServerLogger.Log("Reading response of length {0}", length);
var responseBuffer = new byte[length];
await ServerProtocol.ReadAllAsync(
stream,
diff --git a/test/Microsoft.AspNetCore.Razor.Design.Test/IntegrationTests/BuildServerIntegrationTest.cs b/test/Microsoft.AspNetCore.Razor.Design.Test/IntegrationTests/BuildServerIntegrationTest.cs
index 1adb5152ab..d7fc51b4dd 100644
--- a/test/Microsoft.AspNetCore.Razor.Design.Test/IntegrationTests/BuildServerIntegrationTest.cs
+++ b/test/Microsoft.AspNetCore.Razor.Design.Test/IntegrationTests/BuildServerIntegrationTest.cs
@@ -24,7 +24,7 @@ namespace Microsoft.AspNetCore.Razor.Design.IntegrationTests
{
var result = await DotnetMSBuild(
"Build",
- $"/p:RazorCompileOnBuild=true /p:UseRazorBuildServer=true /p:_RazorBuildServerPipeName={_pipeName}",
+ $"/p:RazorCompileOnBuild=true /p:UseRazorBuildServer=true /p:_RazorBuildServerPipeName={_pipeName} /p:_RazorForceBuildServer=true",
msBuildProcessKind: msBuildProcessKind);
Assert.BuildPassed(result);
@@ -40,7 +40,7 @@ namespace Microsoft.AspNetCore.Razor.Design.IntegrationTests
{
var result = await DotnetMSBuild(
"Build",
- $"/p:RazorCompileOnBuild=true /p:UseRazorBuildServer=true /p:_RazorBuildServerPipeName={_pipeName}");
+ $"/p:RazorCompileOnBuild=true /p:UseRazorBuildServer=true /p:_RazorBuildServerPipeName={_pipeName} /p:_RazorForceBuildServer=true");
Assert.BuildPassed(result);
Assert.FileExists(result, OutputPath, "SimpleMvc.dll");
@@ -55,7 +55,7 @@ namespace Microsoft.AspNetCore.Razor.Design.IntegrationTests
{
var result = await DotnetMSBuild(
"Build",
- $"/p:RazorCompileOnBuild=true /p:UseRazorBuildServer=true /p:_RazorBuildServerPipeName={_pipeName}");
+ $"/p:RazorCompileOnBuild=true /p:UseRazorBuildServer=true /p:_RazorBuildServerPipeName={_pipeName} /p:_RazorForceBuildServer=true");
Assert.BuildPassed(result);
Assert.FileExists(result, OutputPath, "Whitespace in name.dll");
diff --git a/test/Microsoft.AspNetCore.Razor.Tools.Test/Infrastructure/ServerUtilities.cs b/test/Microsoft.AspNetCore.Razor.Tools.Test/Infrastructure/ServerUtilities.cs
index 77c30cd60a..473b608142 100644
--- a/test/Microsoft.AspNetCore.Razor.Tools.Test/Infrastructure/ServerUtilities.cs
+++ b/test/Microsoft.AspNetCore.Razor.Tools.Test/Infrastructure/ServerUtilities.cs
@@ -6,7 +6,6 @@ using System.Collections.Generic;
using System.IO;
using System.Threading;
using System.Threading.Tasks;
-using Microsoft.CodeAnalysis.CommandLine;
namespace Microsoft.AspNetCore.Razor.Tools
{