Add option to suppress writing startup messages
This commit is contained in:
parent
6687f4eefc
commit
a63932a492
|
|
@ -159,6 +159,17 @@ namespace Microsoft.AspNetCore.Hosting
|
||||||
return hostBuilder.UseSetting(WebHostDefaults.PreferHostingUrlsKey, preferHostingUrls ? "true" : "false");
|
return hostBuilder.UseSetting(WebHostDefaults.PreferHostingUrlsKey, preferHostingUrls ? "true" : "false");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Specify if startup status messages should be suppressed.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="hostBuilder">The <see cref="IWebHostBuilder"/> to configure.</param>
|
||||||
|
/// <param name="suppressStatusMessages"><c>true</c> to suppress writing of hosting startup status messages; otherwise <c>false</c>.</param>
|
||||||
|
/// <returns>The <see cref="IWebHostBuilder"/>.</returns>
|
||||||
|
public static IWebHostBuilder SuppressStatusMessages(this IWebHostBuilder hostBuilder, bool suppressStatusMessages)
|
||||||
|
{
|
||||||
|
return hostBuilder.UseSetting(WebHostDefaults.SuppressStatusMessagesKey, suppressStatusMessages ? "true" : "false");
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Specify the amount of time to wait for the web host to shutdown.
|
/// Specify the amount of time to wait for the web host to shutdown.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
|
||||||
|
|
@ -17,6 +17,7 @@ namespace Microsoft.AspNetCore.Hosting
|
||||||
public static readonly string ContentRootKey = "contentRoot";
|
public static readonly string ContentRootKey = "contentRoot";
|
||||||
public static readonly string PreferHostingUrlsKey = "preferHostingUrls";
|
public static readonly string PreferHostingUrlsKey = "preferHostingUrls";
|
||||||
public static readonly string PreventHostingStartupKey = "preventHostingStartup";
|
public static readonly string PreventHostingStartupKey = "preventHostingStartup";
|
||||||
|
public static readonly string SuppressStatusMessagesKey = "suppressStatusMessages";
|
||||||
|
|
||||||
public static readonly string ShutdownTimeoutKey = "shutdownTimeoutSeconds";
|
public static readonly string ShutdownTimeoutKey = "shutdownTimeoutSeconds";
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -204,8 +204,11 @@ namespace Microsoft.AspNetCore.Hosting.Internal
|
||||||
_applicationServices = _applicationServiceCollection.BuildServiceProvider();
|
_applicationServices = _applicationServiceCollection.BuildServiceProvider();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Write errors to standard out so they can be retrieved when not in development mode.
|
if (!_options.SuppressStatusMessages)
|
||||||
Console.Out.WriteLine("Application startup exception: " + ex.ToString());
|
{
|
||||||
|
// 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<ILogger<WebHost>>();
|
var logger = _applicationServices.GetRequiredService<ILogger<WebHost>>();
|
||||||
logger.ApplicationError(ex);
|
logger.ApplicationError(ex);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -30,6 +30,8 @@ namespace Microsoft.AspNetCore.Hosting.Internal
|
||||||
WebRoot = configuration[WebHostDefaults.WebRootKey];
|
WebRoot = configuration[WebHostDefaults.WebRootKey];
|
||||||
ContentRootPath = configuration[WebHostDefaults.ContentRootKey];
|
ContentRootPath = configuration[WebHostDefaults.ContentRootKey];
|
||||||
PreventHostingStartup = WebHostUtilities.ParseBool(configuration, WebHostDefaults.PreventHostingStartupKey);
|
PreventHostingStartup = WebHostUtilities.ParseBool(configuration, WebHostDefaults.PreventHostingStartupKey);
|
||||||
|
SuppressStatusMessages = WebHostUtilities.ParseBool(configuration, WebHostDefaults.SuppressStatusMessagesKey);
|
||||||
|
|
||||||
// Search the primary assembly and configured assemblies.
|
// Search the primary assembly and configured assemblies.
|
||||||
HostingStartupAssemblies = $"{ApplicationName};{configuration[WebHostDefaults.HostingStartupAssembliesKey]}"
|
HostingStartupAssemblies = $"{ApplicationName};{configuration[WebHostDefaults.HostingStartupAssembliesKey]}"
|
||||||
.Split(new[] { ';' }, StringSplitOptions.RemoveEmptyEntries) ?? new string[0];
|
.Split(new[] { ';' }, StringSplitOptions.RemoveEmptyEntries) ?? new string[0];
|
||||||
|
|
@ -46,6 +48,8 @@ namespace Microsoft.AspNetCore.Hosting.Internal
|
||||||
|
|
||||||
public bool PreventHostingStartup { get; set; }
|
public bool PreventHostingStartup { get; set; }
|
||||||
|
|
||||||
|
public bool SuppressStatusMessages { get; set; }
|
||||||
|
|
||||||
public IReadOnlyList<string> HostingStartupAssemblies { get; set; }
|
public IReadOnlyList<string> HostingStartupAssemblies { get; set; }
|
||||||
|
|
||||||
public bool DetailedErrors { get; set; }
|
public bool DetailedErrors { get; set; }
|
||||||
|
|
|
||||||
|
|
@ -151,26 +151,36 @@ namespace Microsoft.AspNetCore.Hosting
|
||||||
}
|
}
|
||||||
_webHostBuilt = true;
|
_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 hostingServices = BuildCommonServices(out var hostingStartupErrors);
|
||||||
var applicationServices = hostingServices.Clone();
|
var applicationServices = hostingServices.Clone();
|
||||||
var hostingServiceProvider = hostingServices.BuildServiceProvider();
|
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<ILogger<WebHost>>();
|
||||||
|
// 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);
|
AddApplicationServices(applicationServices, hostingServiceProvider);
|
||||||
|
|
||||||
var host = new WebHost(
|
var host = new WebHost(
|
||||||
|
|
@ -228,6 +238,7 @@ namespace Microsoft.AspNetCore.Hosting
|
||||||
_context.HostingEnvironment = _hostingEnvironment;
|
_context.HostingEnvironment = _hostingEnvironment;
|
||||||
|
|
||||||
var services = new ServiceCollection();
|
var services = new ServiceCollection();
|
||||||
|
services.AddSingleton(_options);
|
||||||
services.AddSingleton(_hostingEnvironment);
|
services.AddSingleton(_hostingEnvironment);
|
||||||
services.AddSingleton(_context);
|
services.AddSingleton(_context);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,7 @@ using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Microsoft.AspNetCore.Hosting.Server.Features;
|
using Microsoft.AspNetCore.Hosting.Server.Features;
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
|
using Microsoft.AspNetCore.Hosting.Internal;
|
||||||
|
|
||||||
namespace Microsoft.AspNetCore.Hosting
|
namespace Microsoft.AspNetCore.Hosting
|
||||||
{
|
{
|
||||||
|
|
@ -76,7 +77,8 @@ namespace Microsoft.AspNetCore.Hosting
|
||||||
var done = new ManualResetEventSlim(false);
|
var done = new ManualResetEventSlim(false);
|
||||||
using (var cts = new CancellationTokenSource())
|
using (var cts = new CancellationTokenSource())
|
||||||
{
|
{
|
||||||
AttachCtrlcSigtermShutdown(cts, done, shutdownMessage: "Application is shutting down...");
|
var shutdownMessage = host.Services.GetRequiredService<WebHostOptions>().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.");
|
await host.RunAsync(cts.Token, "Application started. Press Ctrl+C to shut down.");
|
||||||
done.Set();
|
done.Set();
|
||||||
|
|
@ -91,22 +93,27 @@ namespace Microsoft.AspNetCore.Hosting
|
||||||
|
|
||||||
var hostingEnvironment = host.Services.GetService<IHostingEnvironment>();
|
var hostingEnvironment = host.Services.GetService<IHostingEnvironment>();
|
||||||
var applicationLifetime = host.Services.GetService<IApplicationLifetime>();
|
var applicationLifetime = host.Services.GetService<IApplicationLifetime>();
|
||||||
|
var options = host.Services.GetRequiredService<WebHostOptions>();
|
||||||
|
|
||||||
Console.WriteLine($"Hosting environment: {hostingEnvironment.EnvironmentName}");
|
if (!options.SuppressStatusMessages)
|
||||||
Console.WriteLine($"Content root path: {hostingEnvironment.ContentRootPath}");
|
|
||||||
|
|
||||||
var serverAddresses = host.ServerFeatures.Get<IServerAddressesFeature>()?.Addresses;
|
|
||||||
if (serverAddresses != null)
|
|
||||||
{
|
{
|
||||||
foreach (var address in serverAddresses)
|
Console.WriteLine($"Hosting environment: {hostingEnvironment.EnvironmentName}");
|
||||||
|
Console.WriteLine($"Content root path: {hostingEnvironment.ContentRootPath}");
|
||||||
|
|
||||||
|
|
||||||
|
var serverAddresses = host.ServerFeatures.Get<IServerAddressesFeature>()?.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))
|
if (!string.IsNullOrEmpty(shutdownMessage))
|
||||||
{
|
{
|
||||||
Console.WriteLine(shutdownMessage);
|
Console.WriteLine(shutdownMessage);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
await host.WaitForTokenShutdownAsync(token);
|
await host.WaitForTokenShutdownAsync(token);
|
||||||
|
|
|
||||||
|
|
@ -95,6 +95,8 @@ namespace Microsoft.AspNetCore.Server.IntegrationTesting
|
||||||
|
|
||||||
public bool PreservePublishedApplicationForDebugging { get; set; } = false;
|
public bool PreservePublishedApplicationForDebugging { get; set; } = false;
|
||||||
|
|
||||||
|
public bool StatusMessagesEnabled { get; set; } = true;
|
||||||
|
|
||||||
public ApplicationType ApplicationType { get; set; }
|
public ApplicationType ApplicationType { get; set; }
|
||||||
|
|
||||||
public string PublishedApplicationRootPath { get; set; }
|
public string PublishedApplicationRootPath { get; set; }
|
||||||
|
|
|
||||||
|
|
@ -164,10 +164,14 @@ namespace Microsoft.AspNetCore.Server.IntegrationTesting
|
||||||
|
|
||||||
Logger.LogInformation("Started {fileName}. Process Id : {processId}", startInfo.FileName, HostProcess.Id);
|
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
|
// Host may not write startup messages, in which case assume it started
|
||||||
// We cover a lot of error cases above, but I want to make sure we eventually give up and don't hang the build
|
if (DeploymentParameters.StatusMessagesEnabled)
|
||||||
// just in case we missed one -anurse
|
{
|
||||||
await started.Task.TimeoutAfter(TimeSpan.FromMinutes(10));
|
// 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);
|
return (url: actualUrl ?? hintUrl, hostExitToken: hostExitTokenSource.Token);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -6,9 +6,9 @@ namespace Microsoft.Extensions.Hosting
|
||||||
public class ConsoleLifetimeOptions
|
public class ConsoleLifetimeOptions
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Indicates if host lifetime status messages should be written to the console such as on startup.
|
/// Indicates if host lifetime status messages should be supressed such as on startup.
|
||||||
/// The default is true.
|
/// The default is false.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public bool WriteStatusMessages { get; set; } = true;
|
public bool SuppressStatusMessages { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -28,7 +28,7 @@ namespace Microsoft.Extensions.Hosting.Internal
|
||||||
|
|
||||||
public void RegisterDelayStartCallback(Action<object> callback, object state)
|
public void RegisterDelayStartCallback(Action<object> callback, object state)
|
||||||
{
|
{
|
||||||
if (Options.WriteStatusMessages)
|
if (!Options.SuppressStatusMessages)
|
||||||
{
|
{
|
||||||
ApplicationLifetime.ApplicationStarted.Register(() =>
|
ApplicationLifetime.ApplicationStarted.Register(() =>
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,10 @@
|
||||||
// Copyright (c) .NET Foundation. All rights reserved.
|
// Copyright (c) .NET Foundation. All rights reserved.
|
||||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||||
|
|
||||||
|
using System;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Text.RegularExpressions;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Microsoft.AspNetCore.Server.IntegrationTesting;
|
using Microsoft.AspNetCore.Server.IntegrationTesting;
|
||||||
using Microsoft.AspNetCore.Testing;
|
using Microsoft.AspNetCore.Testing;
|
||||||
|
|
@ -16,78 +17,35 @@ namespace Microsoft.AspNetCore.Hosting.FunctionalTests
|
||||||
{
|
{
|
||||||
public class ShutdownTests : LoggedTest
|
public class ShutdownTests : LoggedTest
|
||||||
{
|
{
|
||||||
private static readonly Regex NowListeningRegex = new Regex(@"^\s*Now listening on: (?<url>.*)$");
|
private static readonly string StartedMessage = "Started";
|
||||||
private const string ApplicationStartedMessage = "Application started. Press Ctrl+C to shut down.";
|
private static readonly string CompletionMessage = "Stopping firing\n" +
|
||||||
|
"Stopping end\n" +
|
||||||
|
"Stopped firing\n" +
|
||||||
|
"Stopped end";
|
||||||
|
|
||||||
public ShutdownTests(ITestOutputHelper output) : base(output)
|
public ShutdownTests(ITestOutputHelper output) : base(output) { }
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
[ConditionalFact]
|
[ConditionalFact]
|
||||||
[OSSkipCondition(OperatingSystems.Windows)]
|
[OSSkipCondition(OperatingSystems.Windows)]
|
||||||
[OSSkipCondition(OperatingSystems.MacOSX)]
|
[OSSkipCondition(OperatingSystems.MacOSX)]
|
||||||
public async Task ShutdownTestRun()
|
public async Task ShutdownTestRun()
|
||||||
{
|
{
|
||||||
using (StartLog(out var loggerFactory))
|
await ExecuteShutdownTest(nameof(ShutdownTestRun), "Run");
|
||||||
{
|
|
||||||
var logger = loggerFactory.CreateLogger(nameof(ShutdownTestRun));
|
|
||||||
|
|
||||||
var applicationPath = Path.Combine(TestPathUtilities.GetSolutionRootDirectory("Hosting"), "test", "TestAssets",
|
|
||||||
"Microsoft.AspNetCore.Hosting.TestSites");
|
|
||||||
|
|
||||||
var deploymentParameters = new DeploymentParameters(
|
|
||||||
applicationPath,
|
|
||||||
ServerType.Kestrel,
|
|
||||||
RuntimeFlavor.CoreClr,
|
|
||||||
RuntimeArchitecture.x64)
|
|
||||||
{
|
|
||||||
EnvironmentName = "Shutdown",
|
|
||||||
TargetFramework = "netcoreapp2.0",
|
|
||||||
ApplicationType = ApplicationType.Portable,
|
|
||||||
PublishApplicationBeforeDeployment = true
|
|
||||||
};
|
|
||||||
|
|
||||||
deploymentParameters.EnvironmentVariables["ASPNETCORE_STARTMECHANIC"] = "Run";
|
|
||||||
|
|
||||||
using (var deployer = new SelfHostDeployer(deploymentParameters, loggerFactory))
|
|
||||||
{
|
|
||||||
await deployer.DeployAsync();
|
|
||||||
|
|
||||||
string output = string.Empty;
|
|
||||||
deployer.HostProcess.OutputDataReceived += (sender, args) =>
|
|
||||||
{
|
|
||||||
if (!string.Equals(args.Data, ApplicationStartedMessage)
|
|
||||||
&& !string.IsNullOrEmpty(args.Data)
|
|
||||||
&& !NowListeningRegex.Match(args.Data).Success)
|
|
||||||
{
|
|
||||||
output += args.Data + '\n';
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
SendSIGINT(deployer.HostProcess.Id);
|
|
||||||
|
|
||||||
WaitForExitOrKill(deployer.HostProcess);
|
|
||||||
|
|
||||||
output = output.Trim('\n');
|
|
||||||
|
|
||||||
Assert.Equal("Application is shutting down...\n" +
|
|
||||||
"Stopping firing\n" +
|
|
||||||
"Stopping end\n" +
|
|
||||||
"Stopped firing\n" +
|
|
||||||
"Stopped end",
|
|
||||||
output);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[ConditionalFact]
|
[ConditionalFact]
|
||||||
[OSSkipCondition(OperatingSystems.Windows)]
|
[OSSkipCondition(OperatingSystems.Windows)]
|
||||||
[OSSkipCondition(OperatingSystems.MacOSX)]
|
[OSSkipCondition(OperatingSystems.MacOSX)]
|
||||||
public async Task ShutdownTestWaitForShutdown()
|
public async Task ShutdownTestWaitForShutdown()
|
||||||
|
{
|
||||||
|
await ExecuteShutdownTest(nameof(ShutdownTestWaitForShutdown), "WaitForShutdown");
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task ExecuteShutdownTest(string testName, string shutdownMechanic)
|
||||||
{
|
{
|
||||||
using (StartLog(out var loggerFactory))
|
using (StartLog(out var loggerFactory))
|
||||||
{
|
{
|
||||||
var logger = loggerFactory.CreateLogger(nameof(ShutdownTestWaitForShutdown));
|
var logger = loggerFactory.CreateLogger(testName);
|
||||||
|
|
||||||
var applicationPath = Path.Combine(TestPathUtilities.GetSolutionRootDirectory("Hosting"), "test", "TestAssets",
|
var applicationPath = Path.Combine(TestPathUtilities.GetSolutionRootDirectory("Hosting"), "test", "TestAssets",
|
||||||
"Microsoft.AspNetCore.Hosting.TestSites");
|
"Microsoft.AspNetCore.Hosting.TestSites");
|
||||||
|
|
@ -101,29 +59,58 @@ namespace Microsoft.AspNetCore.Hosting.FunctionalTests
|
||||||
EnvironmentName = "Shutdown",
|
EnvironmentName = "Shutdown",
|
||||||
TargetFramework = "netcoreapp2.0",
|
TargetFramework = "netcoreapp2.0",
|
||||||
ApplicationType = ApplicationType.Portable,
|
ApplicationType = ApplicationType.Portable,
|
||||||
PublishApplicationBeforeDeployment = true
|
PublishApplicationBeforeDeployment = true,
|
||||||
|
StatusMessagesEnabled = false
|
||||||
};
|
};
|
||||||
|
|
||||||
deploymentParameters.EnvironmentVariables["ASPNETCORE_STARTMECHANIC"] = "WaitForShutdown";
|
deploymentParameters.EnvironmentVariables["ASPNETCORE_STARTMECHANIC"] = shutdownMechanic;
|
||||||
|
|
||||||
using (var deployer = new SelfHostDeployer(deploymentParameters, loggerFactory))
|
using (var deployer = new SelfHostDeployer(deploymentParameters, loggerFactory))
|
||||||
{
|
{
|
||||||
await deployer.DeployAsync();
|
await deployer.DeployAsync();
|
||||||
|
|
||||||
string output = string.Empty;
|
var started = new ManualResetEventSlim();
|
||||||
deployer.HostProcess.OutputDataReceived += (sender, args) => output += args.Data + '\n';
|
var completed = new ManualResetEventSlim();
|
||||||
|
var output = string.Empty;
|
||||||
|
deployer.HostProcess.OutputDataReceived += (sender, args) =>
|
||||||
|
{
|
||||||
|
if (!string.IsNullOrEmpty(args.Data) && args.Data.StartsWith(StartedMessage))
|
||||||
|
{
|
||||||
|
started.Set();
|
||||||
|
output += args.Data.Substring(StartedMessage.Length) + '\n';
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
output += args.Data + '\n';
|
||||||
|
}
|
||||||
|
|
||||||
|
if (output.Contains(CompletionMessage))
|
||||||
|
{
|
||||||
|
completed.Set();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
started.Wait(50000);
|
||||||
|
|
||||||
|
if (!started.IsSet)
|
||||||
|
{
|
||||||
|
throw new InvalidOperationException("Application did not start successfully");
|
||||||
|
}
|
||||||
|
|
||||||
SendSIGINT(deployer.HostProcess.Id);
|
SendSIGINT(deployer.HostProcess.Id);
|
||||||
|
|
||||||
WaitForExitOrKill(deployer.HostProcess);
|
WaitForExitOrKill(deployer.HostProcess);
|
||||||
|
|
||||||
|
completed.Wait(50000);
|
||||||
|
|
||||||
|
if (!started.IsSet)
|
||||||
|
{
|
||||||
|
throw new InvalidOperationException($"Application did not write the expected output. The received output is: {output}");
|
||||||
|
}
|
||||||
|
|
||||||
output = output.Trim('\n');
|
output = output.Trim('\n');
|
||||||
|
|
||||||
Assert.Equal("Stopping firing\n" +
|
Assert.Equal(CompletionMessage, output);
|
||||||
"Stopping end\n" +
|
|
||||||
"Stopped firing\n" +
|
|
||||||
"Stopped end",
|
|
||||||
output);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,6 @@
|
||||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||||
|
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Text.RegularExpressions;
|
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Microsoft.AspNetCore.Server.IntegrationTesting;
|
using Microsoft.AspNetCore.Server.IntegrationTesting;
|
||||||
|
|
@ -16,12 +15,7 @@ namespace Microsoft.AspNetCore.Hosting.FunctionalTests
|
||||||
{
|
{
|
||||||
public class WebHostBuilderTests : LoggedTest
|
public class WebHostBuilderTests : LoggedTest
|
||||||
{
|
{
|
||||||
private static readonly Regex NowListeningRegex = new Regex(@"^\s*Now listening on: (?<url>.*)$");
|
public WebHostBuilderTests(ITestOutputHelper output) : base(output) { }
|
||||||
private const string ApplicationStartedMessage = "Application started. Press Ctrl+C to shut down.";
|
|
||||||
|
|
||||||
public WebHostBuilderTests(ITestOutputHelper output) : base(output)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public async Task InjectedStartup_DefaultApplicationNameIsEntryAssembly_CoreClr()
|
public async Task InjectedStartup_DefaultApplicationNameIsEntryAssembly_CoreClr()
|
||||||
|
|
@ -48,7 +42,8 @@ namespace Microsoft.AspNetCore.Hosting.FunctionalTests
|
||||||
RuntimeArchitecture.x64)
|
RuntimeArchitecture.x64)
|
||||||
{
|
{
|
||||||
TargetFramework = runtimeFlavor == RuntimeFlavor.Clr ? "net461" : "netcoreapp2.0",
|
TargetFramework = runtimeFlavor == RuntimeFlavor.Clr ? "net461" : "netcoreapp2.0",
|
||||||
ApplicationType = ApplicationType.Portable
|
ApplicationType = ApplicationType.Portable,
|
||||||
|
StatusMessagesEnabled = false
|
||||||
};
|
};
|
||||||
|
|
||||||
using (var deployer = new SelfHostDeployer(deploymentParameters, loggerFactory))
|
using (var deployer = new SelfHostDeployer(deploymentParameters, loggerFactory))
|
||||||
|
|
@ -59,16 +54,14 @@ namespace Microsoft.AspNetCore.Hosting.FunctionalTests
|
||||||
var mre = new ManualResetEventSlim();
|
var mre = new ManualResetEventSlim();
|
||||||
deployer.HostProcess.OutputDataReceived += (sender, args) =>
|
deployer.HostProcess.OutputDataReceived += (sender, args) =>
|
||||||
{
|
{
|
||||||
if (!string.Equals(args.Data, ApplicationStartedMessage)
|
if (!string.IsNullOrWhiteSpace(args.Data))
|
||||||
&& !string.IsNullOrEmpty(args.Data)
|
|
||||||
&& !NowListeningRegex.Match(args.Data).Success)
|
|
||||||
{
|
{
|
||||||
output += args.Data + '\n';
|
output += args.Data + '\n';
|
||||||
mre.Set();
|
mre.Set();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
mre.Wait(10000);
|
mre.Wait(50000);
|
||||||
|
|
||||||
output = output.Trim('\n');
|
output = output.Trim('\n');
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -15,12 +15,13 @@ namespace Microsoft.AspNetCore.Hosting.Tests
|
||||||
{
|
{
|
||||||
var parameters = new Dictionary<string, string>()
|
var parameters = new Dictionary<string, string>()
|
||||||
{
|
{
|
||||||
{ "webroot", "wwwroot"},
|
{ WebHostDefaults.WebRootKey, "wwwroot"},
|
||||||
{ "applicationName", "MyProjectReference"},
|
{ WebHostDefaults.ApplicationKey, "MyProjectReference"},
|
||||||
{ "startupAssembly", "MyProjectReference" },
|
{ WebHostDefaults.StartupAssemblyKey, "MyProjectReference" },
|
||||||
{ "environment", EnvironmentName.Development},
|
{ WebHostDefaults.EnvironmentKey, EnvironmentName.Development},
|
||||||
{ "detailederrors", "true"},
|
{ WebHostDefaults.DetailedErrorsKey, "true"},
|
||||||
{ "captureStartupErrors", "true" }
|
{ WebHostDefaults.CaptureStartupErrorsKey, "true" },
|
||||||
|
{ WebHostDefaults.SuppressStatusMessagesKey, "true" }
|
||||||
};
|
};
|
||||||
|
|
||||||
var config = new WebHostOptions(new ConfigurationBuilder().AddInMemoryCollection(parameters).Build());
|
var config = new WebHostOptions(new ConfigurationBuilder().AddInMemoryCollection(parameters).Build());
|
||||||
|
|
@ -31,6 +32,7 @@ namespace Microsoft.AspNetCore.Hosting.Tests
|
||||||
Assert.Equal(EnvironmentName.Development, config.Environment);
|
Assert.Equal(EnvironmentName.Development, config.Environment);
|
||||||
Assert.True(config.CaptureStartupErrors);
|
Assert.True(config.CaptureStartupErrors);
|
||||||
Assert.True(config.DetailedErrors);
|
Assert.True(config.DetailedErrors);
|
||||||
|
Assert.True(config.SuppressStatusMessages);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
|
|
|
||||||
|
|
@ -15,15 +15,11 @@ namespace IStartupInjectionAssemblyName
|
||||||
{
|
{
|
||||||
var server = new TestServer(CreateWebHostBuilder(args));
|
var server = new TestServer(CreateWebHostBuilder(args));
|
||||||
|
|
||||||
// Mimic application startup messages so application deployer knows that the application has started
|
|
||||||
Console.WriteLine("Application started. Press Ctrl+C to shut down.");
|
|
||||||
Console.WriteLine("Now listening on: http://localhost:5000");
|
|
||||||
|
|
||||||
Task.Run(async () => Console.WriteLine(await server.CreateClient().GetStringAsync(""))).GetAwaiter().GetResult();
|
Task.Run(async () => Console.WriteLine(await server.CreateClient().GetStringAsync(""))).GetAwaiter().GetResult();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Do not change the signature of this method. It's used for tests.
|
// Do not change the signature of this method. It's used for tests.
|
||||||
private static IWebHostBuilder CreateWebHostBuilder(string [] args) =>
|
private static IWebHostBuilder CreateWebHostBuilder(string [] args) =>
|
||||||
new WebHostBuilder().ConfigureServices(services => services.AddSingleton<IStartup, Startup>());
|
new WebHostBuilder().SuppressStatusMessages(true).ConfigureServices(services => services.AddSingleton<IStartup, Startup>());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,27 +0,0 @@
|
||||||
{
|
|
||||||
"iisSettings": {
|
|
||||||
"windowsAuthentication": false,
|
|
||||||
"anonymousAuthentication": true,
|
|
||||||
"iisExpress": {
|
|
||||||
"applicationUrl": "http://localhost:50801/",
|
|
||||||
"sslPort": 0
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"profiles": {
|
|
||||||
"IIS Express": {
|
|
||||||
"commandName": "IISExpress",
|
|
||||||
"launchBrowser": true,
|
|
||||||
"environmentVariables": {
|
|
||||||
"ASPNETCORE_ENVIRONMENT": "Development"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"IStartupInjectionAssemblyName": {
|
|
||||||
"commandName": "Project",
|
|
||||||
"launchBrowser": true,
|
|
||||||
"environmentVariables": {
|
|
||||||
"ASPNETCORE_ENVIRONMENT": "Development"
|
|
||||||
},
|
|
||||||
"applicationUrl": "http://localhost:50802/"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -8,7 +8,6 @@ using Microsoft.AspNetCore.Hosting;
|
||||||
using Microsoft.AspNetCore.Hosting.Server;
|
using Microsoft.AspNetCore.Hosting.Server;
|
||||||
using Microsoft.AspNetCore.Http.Features;
|
using Microsoft.AspNetCore.Http.Features;
|
||||||
using Microsoft.Extensions.Configuration;
|
using Microsoft.Extensions.Configuration;
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
using Microsoft.Extensions.Logging.Console;
|
using Microsoft.Extensions.Logging.Console;
|
||||||
|
|
||||||
|
|
@ -26,6 +25,7 @@ namespace ServerComparison.TestSites
|
||||||
var builder = new WebHostBuilder()
|
var builder = new WebHostBuilder()
|
||||||
.UseServer(new NoopServer())
|
.UseServer(new NoopServer())
|
||||||
.UseConfiguration(config)
|
.UseConfiguration(config)
|
||||||
|
.SuppressStatusMessages(true)
|
||||||
.ConfigureLogging((_, factory) =>
|
.ConfigureLogging((_, factory) =>
|
||||||
{
|
{
|
||||||
factory.AddConsole();
|
factory.AddConsole();
|
||||||
|
|
@ -45,10 +45,6 @@ namespace ServerComparison.TestSites
|
||||||
{
|
{
|
||||||
host.Start();
|
host.Start();
|
||||||
|
|
||||||
// Mimic application startup messages so application deployer knows that the application has started
|
|
||||||
Console.WriteLine("Application started. Press Ctrl+C to shut down.");
|
|
||||||
Console.WriteLine("Now listening on: http://localhost:5000");
|
|
||||||
|
|
||||||
host.WaitForShutdown();
|
host.WaitForShutdown();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,27 +0,0 @@
|
||||||
{
|
|
||||||
"iisSettings": {
|
|
||||||
"windowsAuthentication": false,
|
|
||||||
"anonymousAuthentication": true,
|
|
||||||
"iisExpress": {
|
|
||||||
"applicationUrl": "http://localhost:50800/",
|
|
||||||
"sslPort": 0
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"profiles": {
|
|
||||||
"IIS Express": {
|
|
||||||
"commandName": "IISExpress",
|
|
||||||
"launchBrowser": true,
|
|
||||||
"environmentVariables": {
|
|
||||||
"ASPNETCORE_ENVIRONMENT": "Development"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"Microsoft.AspNetCore.Hosting.TestSites": {
|
|
||||||
"commandName": "Project",
|
|
||||||
"launchBrowser": true,
|
|
||||||
"environmentVariables": {
|
|
||||||
"ASPNETCORE_ENVIRONMENT": "Development"
|
|
||||||
},
|
|
||||||
"applicationUrl": "http://localhost:50803/"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -12,6 +12,10 @@ namespace Microsoft.AspNetCore.Hosting.TestSites
|
||||||
{
|
{
|
||||||
public void Configure(IApplicationBuilder app, ILoggerFactory loggerFactory, IApplicationLifetime lifetime)
|
public void Configure(IApplicationBuilder app, ILoggerFactory loggerFactory, IApplicationLifetime lifetime)
|
||||||
{
|
{
|
||||||
|
lifetime.ApplicationStarted.Register(() =>
|
||||||
|
{
|
||||||
|
Console.WriteLine("Started");
|
||||||
|
});
|
||||||
lifetime.ApplicationStopping.Register(() =>
|
lifetime.ApplicationStopping.Register(() =>
|
||||||
{
|
{
|
||||||
Console.WriteLine("Stopping firing");
|
Console.WriteLine("Stopping firing");
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue