diff --git a/Hosting.sln b/Hosting.sln index a04fd5e533..ea81db18f9 100644 --- a/Hosting.sln +++ b/Hosting.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio 14 -VisualStudioVersion = 14.0.23107.0 +VisualStudioVersion = 14.0.24720.0 MinimumVisualStudioVersion = 10.0.40219.1 Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{E0497F39-AFFB-4819-A116-E39E361915AB}" EndProject @@ -30,6 +30,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "samples", "samples", "{9C75 EndProject Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "SampleStartups", "samples\SampleStartups\SampleStartups.xproj", "{485B6745-7648-400A-A969-F68FCF194E46}" EndProject +Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Microsoft.AspNet.Hosting.WindowsServices", "src\Microsoft.AspNet.Hosting.WindowsServices\Microsoft.AspNet.Hosting.WindowsServices.xproj", "{03148731-EA95-40A2-BAE8-A12315EA1748}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -128,6 +130,18 @@ Global {485B6745-7648-400A-A969-F68FCF194E46}.Release|Mixed Platforms.Build.0 = Release|Any CPU {485B6745-7648-400A-A969-F68FCF194E46}.Release|x86.ActiveCfg = Release|Any CPU {485B6745-7648-400A-A969-F68FCF194E46}.Release|x86.Build.0 = Release|Any CPU + {03148731-EA95-40A2-BAE8-A12315EA1748}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {03148731-EA95-40A2-BAE8-A12315EA1748}.Debug|Any CPU.Build.0 = Debug|Any CPU + {03148731-EA95-40A2-BAE8-A12315EA1748}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {03148731-EA95-40A2-BAE8-A12315EA1748}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU + {03148731-EA95-40A2-BAE8-A12315EA1748}.Debug|x86.ActiveCfg = Debug|Any CPU + {03148731-EA95-40A2-BAE8-A12315EA1748}.Debug|x86.Build.0 = Debug|Any CPU + {03148731-EA95-40A2-BAE8-A12315EA1748}.Release|Any CPU.ActiveCfg = Release|Any CPU + {03148731-EA95-40A2-BAE8-A12315EA1748}.Release|Any CPU.Build.0 = Release|Any CPU + {03148731-EA95-40A2-BAE8-A12315EA1748}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU + {03148731-EA95-40A2-BAE8-A12315EA1748}.Release|Mixed Platforms.Build.0 = Release|Any CPU + {03148731-EA95-40A2-BAE8-A12315EA1748}.Release|x86.ActiveCfg = Release|Any CPU + {03148731-EA95-40A2-BAE8-A12315EA1748}.Release|x86.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -141,5 +155,6 @@ Global {FDBBA081-5248-4FC0-9E08-B46BEF3FA438} = {E0497F39-AFFB-4819-A116-E39E361915AB} {3DA89347-6731-4366-80C4-548F24E8607B} = {E0497F39-AFFB-4819-A116-E39E361915AB} {485B6745-7648-400A-A969-F68FCF194E46} = {9C7520A0-F2EB-411C-8BB2-80B39C937217} + {03148731-EA95-40A2-BAE8-A12315EA1748} = {E0497F39-AFFB-4819-A116-E39E361915AB} EndGlobalSection EndGlobal diff --git a/src/Microsoft.AspNet.Hosting.WindowsServices/Microsoft.AspNet.Hosting.WindowsServices.xproj b/src/Microsoft.AspNet.Hosting.WindowsServices/Microsoft.AspNet.Hosting.WindowsServices.xproj new file mode 100644 index 0000000000..39ccb16031 --- /dev/null +++ b/src/Microsoft.AspNet.Hosting.WindowsServices/Microsoft.AspNet.Hosting.WindowsServices.xproj @@ -0,0 +1,19 @@ + + + + 14.0 + $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) + + + + 03148731-ea95-40a2-bae8-a12315ea1748 + Microsoft.AspNet.Hosting.WindowsServices + ..\..\artifacts\obj\$(MSBuildProjectName) + ..\..\artifacts\bin\$(MSBuildProjectName)\ + + + 2.0 + + + + \ No newline at end of file diff --git a/src/Microsoft.AspNet.Hosting.WindowsServices/WebApplicationExtensions.cs b/src/Microsoft.AspNet.Hosting.WindowsServices/WebApplicationExtensions.cs new file mode 100644 index 0000000000..4eb008faa9 --- /dev/null +++ b/src/Microsoft.AspNet.Hosting.WindowsServices/WebApplicationExtensions.cs @@ -0,0 +1,39 @@ +using System.ServiceProcess; + +namespace Microsoft.AspNet.Hosting.WindowsServices +{ + /// + /// Extensions to + /// + public static class WebApplicationExtensions + { + /// + /// Runs the specified web application inside a Windows service and blocks until the service is stopped. + /// + /// An instance of the to host in the Windows service. + /// + /// This example shows how to use . + /// + /// public class Program + /// { + /// public static void Main(string[] args) + /// { + /// var config = WebApplicationConfiguration.GetDefault(args); + /// + /// var application = new WebApplicationBuilder() + /// .UseConfiguration(config) + /// .Build(); + /// + /// // This call will block until the service is stopped. + /// application.RunAsService(); + /// } + /// } + /// + /// + public static void RunAsService(this IWebApplication application) + { + var webApplicationService = new WebApplicationService(application); + ServiceBase.Run(webApplicationService); + } + } +} diff --git a/src/Microsoft.AspNet.Hosting.WindowsServices/WebApplicationService.cs b/src/Microsoft.AspNet.Hosting.WindowsServices/WebApplicationService.cs new file mode 100644 index 0000000000..11819d3411 --- /dev/null +++ b/src/Microsoft.AspNet.Hosting.WindowsServices/WebApplicationService.cs @@ -0,0 +1,80 @@ +using Microsoft.AspNet.Hosting.Internal; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.DependencyInjection; +using System; +using System.ServiceProcess; + +namespace Microsoft.AspNet.Hosting.WindowsServices +{ + /// + /// Provides an implementation of a Windows service that hosts ASP.NET. + /// + public class WebApplicationService : ServiceBase + { + private const string HostingJsonFile = "hosting.json"; + private const string EnvironmentVariablesPrefix = "ASPNET_"; + private const string ConfigFileKey = "config"; + private IWebApplication _application; + private IDisposable _applicationShutdown; + private bool _stopRequestedByWindows; + + /// + /// Creates an instance of WebApplicationService which hosts the specified web application. + /// + /// The web application to host in the Windows service. + public WebApplicationService(IWebApplication application) + { + _application = application; + } + + protected sealed override void OnStart(string[] args) + { + OnStarting(args); + + _application + .Services + .GetRequiredService() + .ApplicationStopped + .Register(() => + { + if (!_stopRequestedByWindows) + { + Stop(); + } + }); + + _applicationShutdown = _application.Start(); + + OnStarted(); + } + + protected sealed override void OnStop() + { + _stopRequestedByWindows = true; + OnStopping(); + _applicationShutdown?.Dispose(); + OnStopped(); + } + + /// + /// Executes before ASP.NET starts. + /// + /// The command line arguments passed to the service. + protected virtual void OnStarting(string[] args) { } + + /// + /// Executes after ASP.NET starts. + /// + protected virtual void OnStarted() { } + + /// + /// Executes before ASP.NET shuts down. + /// + protected virtual void OnStopping() { } + + /// + /// Executes after ASP.NET shuts down. + /// + protected virtual void OnStopped() { } + } +} diff --git a/src/Microsoft.AspNet.Hosting.WindowsServices/project.json b/src/Microsoft.AspNet.Hosting.WindowsServices/project.json new file mode 100644 index 0000000000..3da4890272 --- /dev/null +++ b/src/Microsoft.AspNet.Hosting.WindowsServices/project.json @@ -0,0 +1,22 @@ +{ + "version": "1.0.0-*", + "description": "ASP.NET 5 core hosting infrastructure and startup logic for web applications running within a Windows service.", + "repository": { + "type": "git", + "url": "git://github.com/aspnet/hosting" + }, + "compilationOptions": { + "warningsAsErrors": true, + "keyFile": "../../tools/Key.snk" + }, + "dependencies": { + "Microsoft.AspNet.Hosting": "1.0.0-*" + }, + "frameworks": { + "net451": { + "frameworkAssemblies": { + "System.ServiceProcess": "" + } + } + } +}