diff --git a/src/Microsoft.AspNetCore.Hosting.Abstractions/HostingAbstractionsWebHostBuilderExtensions.cs b/src/Microsoft.AspNetCore.Hosting.Abstractions/HostingAbstractionsWebHostBuilderExtensions.cs
index 76bb2fec1a..f61b86eb86 100644
--- a/src/Microsoft.AspNetCore.Hosting.Abstractions/HostingAbstractionsWebHostBuilderExtensions.cs
+++ b/src/Microsoft.AspNetCore.Hosting.Abstractions/HostingAbstractionsWebHostBuilderExtensions.cs
@@ -159,6 +159,17 @@ namespace Microsoft.AspNetCore.Hosting
return hostBuilder.UseSetting(WebHostDefaults.PreferHostingUrlsKey, preferHostingUrls ? "true" : "false");
}
+ ///
+ /// Specify if startup status messages should be suppressed.
+ ///
+ /// The to configure.
+ /// true to suppress writing of hosting startup status messages; otherwise false.
+ /// The .
+ public static IWebHostBuilder SuppressStatusMessages(this IWebHostBuilder hostBuilder, bool suppressStatusMessages)
+ {
+ return hostBuilder.UseSetting(WebHostDefaults.SuppressStatusMessagesKey, suppressStatusMessages ? "true" : "false");
+ }
+
///
/// Specify the amount of time to wait for the web host to shutdown.
///
diff --git a/src/Microsoft.AspNetCore.Hosting.Abstractions/WebHostDefaults.cs b/src/Microsoft.AspNetCore.Hosting.Abstractions/WebHostDefaults.cs
index cf0edb62b8..5f57a07dce 100644
--- a/src/Microsoft.AspNetCore.Hosting.Abstractions/WebHostDefaults.cs
+++ b/src/Microsoft.AspNetCore.Hosting.Abstractions/WebHostDefaults.cs
@@ -17,6 +17,7 @@ namespace Microsoft.AspNetCore.Hosting
public static readonly string ContentRootKey = "contentRoot";
public static readonly string PreferHostingUrlsKey = "preferHostingUrls";
public static readonly string PreventHostingStartupKey = "preventHostingStartup";
+ public static readonly string SuppressStatusMessagesKey = "suppressStatusMessages";
public static readonly string ShutdownTimeoutKey = "shutdownTimeoutSeconds";
}
diff --git a/src/Microsoft.AspNetCore.Hosting/Internal/WebHost.cs b/src/Microsoft.AspNetCore.Hosting/Internal/WebHost.cs
index a2789a1153..540b6a0ecc 100644
--- a/src/Microsoft.AspNetCore.Hosting/Internal/WebHost.cs
+++ b/src/Microsoft.AspNetCore.Hosting/Internal/WebHost.cs
@@ -204,8 +204,11 @@ namespace Microsoft.AspNetCore.Hosting.Internal
_applicationServices = _applicationServiceCollection.BuildServiceProvider();
}
- // Write errors to standard out so they can be retrieved when not in development mode.
- Console.Out.WriteLine("Application startup exception: " + ex.ToString());
+ if (!_options.SuppressStatusMessages)
+ {
+ // Write errors to standard out so they can be retrieved when not in development mode.
+ Console.WriteLine("Application startup exception: " + ex.ToString());
+ }
var logger = _applicationServices.GetRequiredService>();
logger.ApplicationError(ex);
diff --git a/src/Microsoft.AspNetCore.Hosting/Internal/WebHostOptions.cs b/src/Microsoft.AspNetCore.Hosting/Internal/WebHostOptions.cs
index ba5183992a..7894e3ba5f 100644
--- a/src/Microsoft.AspNetCore.Hosting/Internal/WebHostOptions.cs
+++ b/src/Microsoft.AspNetCore.Hosting/Internal/WebHostOptions.cs
@@ -30,6 +30,8 @@ namespace Microsoft.AspNetCore.Hosting.Internal
WebRoot = configuration[WebHostDefaults.WebRootKey];
ContentRootPath = configuration[WebHostDefaults.ContentRootKey];
PreventHostingStartup = WebHostUtilities.ParseBool(configuration, WebHostDefaults.PreventHostingStartupKey);
+ SuppressStatusMessages = WebHostUtilities.ParseBool(configuration, WebHostDefaults.SuppressStatusMessagesKey);
+
// Search the primary assembly and configured assemblies.
HostingStartupAssemblies = $"{ApplicationName};{configuration[WebHostDefaults.HostingStartupAssembliesKey]}"
.Split(new[] { ';' }, StringSplitOptions.RemoveEmptyEntries) ?? new string[0];
@@ -46,6 +48,8 @@ namespace Microsoft.AspNetCore.Hosting.Internal
public bool PreventHostingStartup { get; set; }
+ public bool SuppressStatusMessages { get; set; }
+
public IReadOnlyList HostingStartupAssemblies { get; set; }
public bool DetailedErrors { get; set; }
diff --git a/src/Microsoft.AspNetCore.Hosting/WebHostBuilder.cs b/src/Microsoft.AspNetCore.Hosting/WebHostBuilder.cs
index 32a0093fcc..7c9a9950ae 100644
--- a/src/Microsoft.AspNetCore.Hosting/WebHostBuilder.cs
+++ b/src/Microsoft.AspNetCore.Hosting/WebHostBuilder.cs
@@ -151,26 +151,36 @@ namespace Microsoft.AspNetCore.Hosting
}
_webHostBuilt = true;
- // Warn about deprecated environment variables
- if (Environment.GetEnvironmentVariable("Hosting:Environment") != null)
- {
- Console.WriteLine("The environment variable 'Hosting:Environment' is obsolete and has been replaced with 'ASPNETCORE_ENVIRONMENT'");
- }
-
- if (Environment.GetEnvironmentVariable("ASPNET_ENV") != null)
- {
- Console.WriteLine("The environment variable 'ASPNET_ENV' is obsolete and has been replaced with 'ASPNETCORE_ENVIRONMENT'");
- }
-
- if (Environment.GetEnvironmentVariable("ASPNETCORE_SERVER.URLS") != null)
- {
- Console.WriteLine("The environment variable 'ASPNETCORE_SERVER.URLS' is obsolete and has been replaced with 'ASPNETCORE_URLS'");
- }
-
var hostingServices = BuildCommonServices(out var hostingStartupErrors);
var applicationServices = hostingServices.Clone();
var hostingServiceProvider = hostingServices.BuildServiceProvider();
+ if (!_options.SuppressStatusMessages)
+ {
+ // Warn about deprecated environment variables
+ if (Environment.GetEnvironmentVariable("Hosting:Environment") != null)
+ {
+ Console.WriteLine("The environment variable 'Hosting:Environment' is obsolete and has been replaced with 'ASPNETCORE_ENVIRONMENT'");
+ }
+
+ if (Environment.GetEnvironmentVariable("ASPNET_ENV") != null)
+ {
+ Console.WriteLine("The environment variable 'ASPNET_ENV' is obsolete and has been replaced with 'ASPNETCORE_ENVIRONMENT'");
+ }
+
+ if (Environment.GetEnvironmentVariable("ASPNETCORE_SERVER.URLS") != null)
+ {
+ Console.WriteLine("The environment variable 'ASPNETCORE_SERVER.URLS' is obsolete and has been replaced with 'ASPNETCORE_URLS'");
+ }
+ }
+
+ var logger = hostingServiceProvider.GetRequiredService>();
+ // Warn about duplicate HostingStartupAssemblies
+ foreach (var assemblyName in _options.HostingStartupAssemblies.GroupBy(a => a, StringComparer.OrdinalIgnoreCase).Where(g => g.Count() > 1))
+ {
+ logger.LogWarning($"The assembly {assemblyName} was specified multiple times. Hosting startup assemblies should only be specified once.");
+ }
+
AddApplicationServices(applicationServices, hostingServiceProvider);
var host = new WebHost(
@@ -228,6 +238,7 @@ namespace Microsoft.AspNetCore.Hosting
_context.HostingEnvironment = _hostingEnvironment;
var services = new ServiceCollection();
+ services.AddSingleton(_options);
services.AddSingleton(_hostingEnvironment);
services.AddSingleton(_context);
diff --git a/src/Microsoft.AspNetCore.Hosting/WebHostExtensions.cs b/src/Microsoft.AspNetCore.Hosting/WebHostExtensions.cs
index d87de05af4..06a3e00cf8 100644
--- a/src/Microsoft.AspNetCore.Hosting/WebHostExtensions.cs
+++ b/src/Microsoft.AspNetCore.Hosting/WebHostExtensions.cs
@@ -6,6 +6,7 @@ using System.Threading;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Hosting.Server.Features;
using Microsoft.Extensions.DependencyInjection;
+using Microsoft.AspNetCore.Hosting.Internal;
namespace Microsoft.AspNetCore.Hosting
{
@@ -76,7 +77,8 @@ namespace Microsoft.AspNetCore.Hosting
var done = new ManualResetEventSlim(false);
using (var cts = new CancellationTokenSource())
{
- AttachCtrlcSigtermShutdown(cts, done, shutdownMessage: "Application is shutting down...");
+ var shutdownMessage = host.Services.GetRequiredService().SuppressStatusMessages ? string.Empty : "Application is shutting down...";
+ AttachCtrlcSigtermShutdown(cts, done, shutdownMessage: shutdownMessage);
await host.RunAsync(cts.Token, "Application started. Press Ctrl+C to shut down.");
done.Set();
@@ -91,22 +93,27 @@ namespace Microsoft.AspNetCore.Hosting
var hostingEnvironment = host.Services.GetService();
var applicationLifetime = host.Services.GetService();
+ var options = host.Services.GetRequiredService();
- Console.WriteLine($"Hosting environment: {hostingEnvironment.EnvironmentName}");
- Console.WriteLine($"Content root path: {hostingEnvironment.ContentRootPath}");
-
- var serverAddresses = host.ServerFeatures.Get()?.Addresses;
- if (serverAddresses != null)
+ if (!options.SuppressStatusMessages)
{
- foreach (var address in serverAddresses)
+ Console.WriteLine($"Hosting environment: {hostingEnvironment.EnvironmentName}");
+ Console.WriteLine($"Content root path: {hostingEnvironment.ContentRootPath}");
+
+
+ var serverAddresses = host.ServerFeatures.Get()?.Addresses;
+ if (serverAddresses != null)
{
- Console.WriteLine($"Now listening on: {address}");
+ foreach (var address in serverAddresses)
+ {
+ Console.WriteLine($"Now listening on: {address}");
+ }
}
- }
- if (!string.IsNullOrEmpty(shutdownMessage))
- {
- Console.WriteLine(shutdownMessage);
+ if (!string.IsNullOrEmpty(shutdownMessage))
+ {
+ Console.WriteLine(shutdownMessage);
+ }
}
await host.WaitForTokenShutdownAsync(token);
diff --git a/src/Microsoft.AspNetCore.Server.IntegrationTesting/Common/DeploymentParameters.cs b/src/Microsoft.AspNetCore.Server.IntegrationTesting/Common/DeploymentParameters.cs
index d61d266085..23df8c8163 100644
--- a/src/Microsoft.AspNetCore.Server.IntegrationTesting/Common/DeploymentParameters.cs
+++ b/src/Microsoft.AspNetCore.Server.IntegrationTesting/Common/DeploymentParameters.cs
@@ -95,6 +95,8 @@ namespace Microsoft.AspNetCore.Server.IntegrationTesting
public bool PreservePublishedApplicationForDebugging { get; set; } = false;
+ public bool StatusMessagesEnabled { get; set; } = true;
+
public ApplicationType ApplicationType { get; set; }
public string PublishedApplicationRootPath { get; set; }
diff --git a/src/Microsoft.AspNetCore.Server.IntegrationTesting/Deployers/SelfHostDeployer.cs b/src/Microsoft.AspNetCore.Server.IntegrationTesting/Deployers/SelfHostDeployer.cs
index 782e96969c..2974631cd7 100644
--- a/src/Microsoft.AspNetCore.Server.IntegrationTesting/Deployers/SelfHostDeployer.cs
+++ b/src/Microsoft.AspNetCore.Server.IntegrationTesting/Deployers/SelfHostDeployer.cs
@@ -164,10 +164,14 @@ namespace Microsoft.AspNetCore.Server.IntegrationTesting
Logger.LogInformation("Started {fileName}. Process Id : {processId}", startInfo.FileName, HostProcess.Id);
- // The timeout here is large, because we don't know how long the test could need
- // We cover a lot of error cases above, but I want to make sure we eventually give up and don't hang the build
- // just in case we missed one -anurse
- await started.Task.TimeoutAfter(TimeSpan.FromMinutes(10));
+ // Host may not write startup messages, in which case assume it started
+ if (DeploymentParameters.StatusMessagesEnabled)
+ {
+ // The timeout here is large, because we don't know how long the test could need
+ // We cover a lot of error cases above, but I want to make sure we eventually give up and don't hang the build
+ // just in case we missed one -anurse
+ await started.Task.TimeoutAfter(TimeSpan.FromMinutes(10));
+ }
return (url: actualUrl ?? hintUrl, hostExitToken: hostExitTokenSource.Token);
}
diff --git a/src/Microsoft.Extensions.Hosting/ConsoleLifetimeOptions.cs b/src/Microsoft.Extensions.Hosting/ConsoleLifetimeOptions.cs
index fedc0e6fb8..e1aa9a1d4d 100644
--- a/src/Microsoft.Extensions.Hosting/ConsoleLifetimeOptions.cs
+++ b/src/Microsoft.Extensions.Hosting/ConsoleLifetimeOptions.cs
@@ -6,9 +6,9 @@ namespace Microsoft.Extensions.Hosting
public class ConsoleLifetimeOptions
{
///
- /// Indicates if host lifetime status messages should be written to the console such as on startup.
- /// The default is true.
+ /// Indicates if host lifetime status messages should be supressed such as on startup.
+ /// The default is false.
///
- public bool WriteStatusMessages { get; set; } = true;
+ public bool SuppressStatusMessages { get; set; }
}
}
diff --git a/src/Microsoft.Extensions.Hosting/Internal/ConsoleLifetime.cs b/src/Microsoft.Extensions.Hosting/Internal/ConsoleLifetime.cs
index d801786c2d..05197d171f 100644
--- a/src/Microsoft.Extensions.Hosting/Internal/ConsoleLifetime.cs
+++ b/src/Microsoft.Extensions.Hosting/Internal/ConsoleLifetime.cs
@@ -28,7 +28,7 @@ namespace Microsoft.Extensions.Hosting.Internal
public void RegisterDelayStartCallback(Action