From b8ce87b605f72ae67a1ea2b356a7992b5e0a7b3a Mon Sep 17 00:00:00 2001 From: Luke Latham <1622880+guardrex@users.noreply.github.com> Date: Tue, 30 Jan 2018 15:13:04 -0600 Subject: [PATCH 1/2] Update Host a Windows Service topic Update Updates --- aspnetcore/host-and-deploy/windows-service.md | 100 ++++++++--------- .../sample/AspNetCoreService.csproj | 23 ++-- .../windows-service/sample/Program.cs | 40 +++---- .../windows-service/sample/README.md | 43 ++++++++ .../sample/wwwroot/css/site.css | 21 ++++ .../sample/wwwroot/css/site.min.css | 1 + .../sample/wwwroot/favicon.ico | Bin 0 -> 32038 bytes .../sample/wwwroot/images/banner1.svg | 1 + .../sample/wwwroot/images/banner2.svg | 1 + .../sample/wwwroot/images/banner3.svg | 1 + .../sample/wwwroot/images/banner4.svg | 1 + .../windows-service/sample/wwwroot/js/site.js | 1 + .../sample/wwwroot/js/site.min.js | 0 .../sample_snapshot/Program.cs | 104 ++++++++++++++++++ 14 files changed, 254 insertions(+), 83 deletions(-) create mode 100644 aspnetcore/host-and-deploy/windows-service/sample/README.md create mode 100644 aspnetcore/host-and-deploy/windows-service/sample/wwwroot/css/site.css create mode 100644 aspnetcore/host-and-deploy/windows-service/sample/wwwroot/css/site.min.css create mode 100644 aspnetcore/host-and-deploy/windows-service/sample/wwwroot/favicon.ico create mode 100644 aspnetcore/host-and-deploy/windows-service/sample/wwwroot/images/banner1.svg create mode 100644 aspnetcore/host-and-deploy/windows-service/sample/wwwroot/images/banner2.svg create mode 100644 aspnetcore/host-and-deploy/windows-service/sample/wwwroot/images/banner3.svg create mode 100644 aspnetcore/host-and-deploy/windows-service/sample/wwwroot/images/banner4.svg create mode 100644 aspnetcore/host-and-deploy/windows-service/sample/wwwroot/js/site.js create mode 100644 aspnetcore/host-and-deploy/windows-service/sample/wwwroot/js/site.min.js create mode 100644 aspnetcore/host-and-deploy/windows-service/sample_snapshot/Program.cs diff --git a/aspnetcore/host-and-deploy/windows-service.md b/aspnetcore/host-and-deploy/windows-service.md index 3bc0250c4df5..88479fb50b5a 100644 --- a/aspnetcore/host-and-deploy/windows-service.md +++ b/aspnetcore/host-and-deploy/windows-service.md @@ -1,11 +1,11 @@ --- title: Host in a Windows Service author: tdykstra -description: Learn how to host an ASP.NET Core application in a Windows Service. +description: Learn how to host an ASP.NET Core app in a Windows Service. manager: wpickett ms.author: tdykstra ms.custom: mvc -ms.date: 03/30/2017 +ms.date: 01/30/2018 ms.prod: aspnet-core ms.technology: aspnet ms.topic: article @@ -15,106 +15,106 @@ uid: host-and-deploy/windows-service By [Tom Dykstra](https://github.com/tdykstra) -The recommended way to host an ASP.NET Core app on Windows without using IIS is to run it in a [Windows Service](https://docs.microsoft.com/dotnet/framework/windows-services/introduction-to-windows-service-applications). That way it can automatically start after reboots and crashes, without waiting for someone to log in. +The recommended way to host an ASP.NET Core app on Windows without using IIS is to run it in a [Windows Service](/dotnet/framework/windows-services/introduction-to-windows-service-applications). When hosted as a Windows Service, the app can automatically start after reboots and crashes without requiring human intervention. -[View or download sample code](https://github.com/aspnet/Docs/tree/master/aspnetcore/host-and-deploy/windows-service/sample) ([how to download](xref:tutorials/index#how-to-download-a-sample)). See the [Next Steps](#next-steps) section for instructions on how to run it. +[View or download sample code](https://github.com/aspnet/Docs/tree/master/aspnetcore/host-and-deploy/windows-service/sample) ([how to download](xref:tutorials/index#how-to-download-a-sample)). For instrucitons on how to run the sample app, see the sample's *README.md* file. ## Prerequisites -* The app must run on the .NET Framework runtime. In the *.csproj* file, specify appropriate values for [TargetFramework](https://docs.microsoft.com/nuget/schema/target-frameworks) and [RuntimeIdentifier](https://docs.microsoft.com/dotnet/articles/core/rid-catalog). Here's an example: +* The app must run on the .NET Framework runtime. In the *.csproj* file, specify appropriate values for [TargetFramework](/nuget/schema/target-frameworks) and [RuntimeIdentifier](/dotnet/articles/core/rid-catalog). Here's an example: [!code-xml[](windows-service/sample/AspNetCoreService.csproj?range=3-6)] When creating a project in Visual Studio, use the **ASP.NET Core Application (.NET Framework)** template. -* If the app receives requests from the Internet (not just from an internal network), it must use the [WebListener](xref:fundamentals/servers/weblistener) web server rather than [Kestrel](xref:fundamentals/servers/kestrel). Kestrel must be used with IIS for edge deployments. For more information, see [When to use Kestrel with a reverse proxy](xref:fundamentals/servers/kestrel#when-to-use-kestrel-with-a-reverse-proxy). +* If the app receives requests from the Internet (not just from an internal network), it must use the [HTTP.sys](xref:fundamentals/servers/httpsys) web server (formerly known as [WebListener](xref:fundamentals/servers/weblistener) for ASP.NET Core 1.x apps) rather than [Kestrel](xref:fundamentals/servers/kestrel). IIS is recommended for use as a reverse proxy server with Kestrel for edge deployments. For more information, see [When to use Kestrel with a reverse proxy](xref:fundamentals/servers/kestrel#when-to-use-kestrel-with-a-reverse-proxy). ## Getting started This section explains the minimum changes required to set up an existing ASP.NET Core project to run in a service. -* Install the NuGet package [Microsoft.AspNetCore.Hosting.WindowsServices](https://www.nuget.org/packages/Microsoft.AspNetCore.Hosting.WindowsServices/). +1. Install the NuGet package [Microsoft.AspNetCore.Hosting.WindowsServices](https://www.nuget.org/packages/Microsoft.AspNetCore.Hosting.WindowsServices/). -* Make the following changes in `Program.Main`: +1. Make the following changes in `Program.Main`: - * Call `host.RunAsService` instead of `host.Run`. + * Call `host.RunAsService` instead of `host.Run`. - * If the code calls `UseContentRoot`, use a path to the publish location instead of `Directory.GetCurrentDirectory()` - - [!code-csharp[](windows-service/sample/Program.cs?name=ServiceOnly&highlight=3-4,8,14)] + * If the code calls `UseContentRoot`, use a path to the publish location instead of `Directory.GetCurrentDirectory()`. -* Publish the application to a folder. + # [ASP.NET Core 2.x](#tab/aspnetcore2x) - Use [dotnet publish](https://docs.microsoft.com/dotnet/articles/core/tools/dotnet-publish) or a [Visual Studio publish profile](xref:host-and-deploy/visual-studio-publish-profiles) that publishes to a folder. + [!code-csharp[](windows-service/sample/Program.cs?name=ServiceOnly&highlight=3-4,7,12)] -* Test by creating and starting the service. + # [ASP.NET Core 1.x](#tab/aspnetcore1x) - Open an administrator command prompt window to use the [sc.exe](https://technet.microsoft.com/library/bb490995) command-line tool to create and start a service. - - If the service is named MyService, publish the app to `c:\svc`, and the app itself is named AspNetCoreService, the commands would look like this: + [!code-csharp[](windows-service/sample_snapshot/Program.cs?name=ServiceOnly&highlight=3-4,8,14)] + + --- + +1. Publish the app to a folder. Use [dotnet publish](/dotnet/articles/core/tools/dotnet-publish) or a [Visual Studio publish profile](xref:host-and-deploy/visual-studio-publish-profiles) that publishes to a folder. - ```console - sc create MyService binPath="C:\Svc\AspNetCoreService.exe" - sc start MyService - ``` +1. Test by creating and starting the service. - The `binPath` value is the path to the app's executable, including the executable filename itself. + Open an administrator command prompt window to use the [sc.exe](https://technet.microsoft.com/library/bb490995) command-line tool to create and start a service. If the service is named MyService, published to `c:\svc`, and named AspNetCoreService, the commands are: - ![Console window create and start example](windows-service/_static/create-start.png) + ```console + sc create MyService binPath="c:\svc\aspnetcoreservice.exe" + sc start MyService + ``` - When these commands finish, browse to the same path as when running as a console app (by default, `http://localhost:5000`) + The `binPath` value is the path to the app's executable, which includes the executable file name. - ![Running in a service](windows-service/_static/running-in-service.png) + ![Console window create and start example](windows-service/_static/create-start.png) + When these commands finish, browse to the same path as when running as a console app (by default, `http://localhost:5000`): + + ![Running in a service](windows-service/_static/running-in-service.png) ## Provide a way to run outside of a service -It's easier to test and debug when running outside of a service, so it's customary to add code that calls `host.RunAsService` only under certain conditions. For example, the app can run as a console app with a `--console` command-line argument or if the debugger is attached. +It's easier to test and debug when running outside of a service, so it's customary to add code that calls `RunAsService` only under certain conditions. For example, the app can run as a console app with a `--console` command-line argument or if the debugger is attached: -[!code-csharp[](windows-service/sample/Program.cs?name=ServiceOrConsole)] +# [ASP.NET Core 2.x](#tab/aspnetcore2x) -## Handle stopping and starting events +[!code-csharp[](windows-service/sample/Program.cs?name=ServiceOrConsole)] -To handle `OnStarting`, `OnStarted`, and `OnStopping` events, make the following additional changes: +# [ASP.NET Core 1.x](#tab/aspnetcore1x) -* Create a class that derives from `WebHostService`. +[!code-csharp[](windows-service/sample_snapshot/Program.cs?name=ServiceOrConsole)] - [!code-csharp[](windows-service/sample/CustomWebHostService.cs?name=NoLogging)] +--- -* Create an extension method for `IWebHost` that passes the custom `WebHostService` to `ServiceBase.Run`. +## Handle stopping and starting events - [!code-csharp[](windows-service/sample/WebHostServiceExtensions.cs?name=ExtensionsClass)] +To handle `OnStarting`, `OnStarted`, and `OnStopping` events, make the following additional changes: -* In `Program.Main` change call the new extension method instead of `host.RunAsService`. +1. Create a class that derives from `WebHostService`: - [!code-csharp[](windows-service/sample/Program.cs?name=HandleStopStart&highlight=26)] + [!code-csharp[](windows-service/sample/CustomWebHostService.cs?name=NoLogging)] -If the custom `WebHostService` code needs to get a service from dependency injection (such as a logger), get it from the `Services` property of `IWebHost`. +1. Create an extension method for `IWebHost` that passes the custom `WebHostService` to `ServiceBase.Run`: -[!code-csharp[](windows-service/sample/CustomWebHostService.cs?name=Logging&highlight=7)] + [!code-csharp[](windows-service/sample/WebHostServiceExtensions.cs?name=ExtensionsClass)] -## Next steps +1. In `Program.Main`, call the new extension method,`RunAsCustomService`, instead of `RunAsService`: -The [sample application](https://github.com/aspnet/Docs/tree/master/aspnetcore/host-and-deploy/windows-service/sample) that accompanies this article is a simple MVC web app that has been modified as shown in preceding code examples. To run it in a service, do the following steps: + # [ASP.NET Core 2.x](#tab/aspnetcore2x) -* Publish to *c:\svc*. + [!code-csharp[](windows-service/sample/Program.cs?name=HandleStopStart&highlight=24)] -* Open an administrator window. + # [ASP.NET Core 1.x](#tab/aspnetcore1x) -* Enter the following commands: + [!code-csharp[](windows-service/sample_snapshot/Program.cs?name=HandleStopStart&highlight=26)] - ```console - sc create MyService binPath="c:\svc\aspnetcoreservice.exe" - sc start MyService - ``` + --- - * In a browser, go to http://localhost:5000 to verify that it's running. +If the custom `WebHostService` code requires a service from dependency injection (such as a logger), obtain it from the `Services` property of `IWebHost`: -If the app doesn't start up as expected when running in a service, a quick way to make error messages accessible is to add a logging provider such as the [Windows EventLog provider](xref:fundamentals/logging/index#eventlog). +[!code-csharp[](windows-service/sample/CustomWebHostService.cs?name=Logging&highlight=7)] ## Acknowledgments -This article was written with the help of sources that were already published. The earliest and most useful of them were these: +This article was written with the help of published sources: * [Hosting ASP.NET Core as Windows service](https://stackoverflow.com/questions/37346383/hosting-asp-net-core-as-windows-service/37464074) * [How to host your ASP.NET Core in a Windows Service](https://dotnetthoughts.net/how-to-host-your-aspnet-core-in-a-windows-service/) diff --git a/aspnetcore/host-and-deploy/windows-service/sample/AspNetCoreService.csproj b/aspnetcore/host-and-deploy/windows-service/sample/AspNetCoreService.csproj index 1a49744963b4..1c16926d0113 100644 --- a/aspnetcore/host-and-deploy/windows-service/sample/AspNetCoreService.csproj +++ b/aspnetcore/host-and-deploy/windows-service/sample/AspNetCoreService.csproj @@ -1,21 +1,24 @@  - net452 - win7-x86 + net461 + win7-x64 + - - - - - - - + + + + + + + + - + + Component diff --git a/aspnetcore/host-and-deploy/windows-service/sample/Program.cs b/aspnetcore/host-and-deploy/windows-service/sample/Program.cs index 0c9b26872a68..1bc533dd7769 100644 --- a/aspnetcore/host-and-deploy/windows-service/sample/Program.cs +++ b/aspnetcore/host-and-deploy/windows-service/sample/Program.cs @@ -1,9 +1,9 @@ #define HandleStopStart // or ServiceOnly ServiceOrConsole -using Microsoft.AspNetCore.Hosting; -using Microsoft.AspNetCore.Hosting.WindowsServices; using System.Diagnostics; using System.IO; using System.Linq; +using Microsoft.AspNetCore; +using Microsoft.AspNetCore.Hosting; namespace AspNetCoreService { @@ -16,13 +16,11 @@ public static void Main(string[] args) var pathToExe = Process.GetCurrentProcess().MainModule.FileName; var pathToContentRoot = Path.GetDirectoryName(pathToExe); - var host = new WebHostBuilder() - .UseKestrel() - .UseContentRoot(pathToContentRoot) - .UseIISIntegration() - .UseStartup() - .UseApplicationInsights() - .Build(); + var host = WebHost.CreateDefaultBuilder(args) + .UseContentRoot(pathToContentRoot) + .UseStartup() + .UseApplicationInsights() + .Build(); host.RunAsService(); } @@ -45,13 +43,11 @@ public static void Main(string[] args) pathToContentRoot = Path.GetDirectoryName(pathToExe); } - var host = new WebHostBuilder() - .UseKestrel() - .UseContentRoot(pathToContentRoot) - .UseIISIntegration() - .UseStartup() - .UseApplicationInsights() - .Build(); + var host = WebHost.CreateDefaultBuilder(args) + .UseContentRoot(pathToContentRoot) + .UseStartup() + .UseApplicationInsights() + .Build(); if (isService) { @@ -81,13 +77,11 @@ public static void Main(string[] args) pathToContentRoot = Path.GetDirectoryName(pathToExe); } - var host = new WebHostBuilder() - .UseKestrel() - .UseContentRoot(pathToContentRoot) - .UseIISIntegration() - .UseStartup() - .UseApplicationInsights() - .Build(); + var host = WebHost.CreateDefaultBuilder(args) + .UseContentRoot(pathToContentRoot) + .UseStartup() + .UseApplicationInsights() + .Build(); if (isService) { diff --git a/aspnetcore/host-and-deploy/windows-service/sample/README.md b/aspnetcore/host-and-deploy/windows-service/sample/README.md new file mode 100644 index 000000000000..311a137195fa --- /dev/null +++ b/aspnetcore/host-and-deploy/windows-service/sample/README.md @@ -0,0 +1,43 @@ +# Custom WebHost Service Sample + +This sample shows the recommended way to host an ASP.NET Core app on Windows without using IIS as a Windows Service. This sample demonstrates the features described in [Host an ASP.NET Core app in a Windows Service](https://docs.microsoft.com/aspnet/core/host-and-deploy/windows-service). + +## Instructions + +The sample app is a simple MVC web app modified according to the instructions in [Host an ASP.NET Core app in a Windows Service](https://docs.microsoft.com/aspnet/core/host-and-deploy/windows-service). + +To run the app in a service, perform the following steps: + +1. Create a folder at *c:\svc*. + +1. Publish the app to the folder with `dotnet publish --configuration Release --output c:\\svc`. The command will move the app's assets to the folder, including the required `appsettings.json` file and the `wwwroot` folder with its contents. + +1. Open an **administrator** command prompt. + +1. Execute the following commands: + + ```console + sc create MyService binPath="c:\svc\aspnetcoreservice.exe" + sc start MyService + ``` + +1. In a browser, go to `http://localhost:5000` to verify that the service is running. + +1. To stop the service, use the command: + + ```console + sc stop MyService + ``` + +If the app doesn't start up as expected when running in a service, a quick way to make error messages accessible is to add a logging provider, such as the [Windows EventLog provider](https://docs.microsoft.com/aspnet/core/fundamentals/logging/index#eventlog). Another option is to check the Application Event Log using the Event Viewer on the system. For example, here's an unhandled exception for a FileNotFound error in the Application Event Log: + +```console +Application: AspNetCoreService.exe +Framework Version: v4.0.30319 +Description: The process was terminated due to an unhandled exception. +Exception Info: System.IO.FileNotFoundException + at Microsoft.Extensions.Configuration.FileConfigurationProvider.Load(Boolean) + at Microsoft.Extensions.Configuration.ConfigurationRoot..ctor(System.Collections.Generic.IList`1) + at Microsoft.Extensions.Configuration.ConfigurationBuilder.Build() + ... +``` diff --git a/aspnetcore/host-and-deploy/windows-service/sample/wwwroot/css/site.css b/aspnetcore/host-and-deploy/windows-service/sample/wwwroot/css/site.css new file mode 100644 index 000000000000..c08311ba3868 --- /dev/null +++ b/aspnetcore/host-and-deploy/windows-service/sample/wwwroot/css/site.css @@ -0,0 +1,21 @@ +body { + padding-top: 50px; + padding-bottom: 20px; +} + +h1 { + font-size: 30px; +} + +h2 { + font-size: 24px; +} + +.body-content { + padding-left: 15px; + padding-right: 15px; +} + +.panel-body { + font-size: 16px; +} diff --git a/aspnetcore/host-and-deploy/windows-service/sample/wwwroot/css/site.min.css b/aspnetcore/host-and-deploy/windows-service/sample/wwwroot/css/site.min.css new file mode 100644 index 000000000000..69c38efcc68d --- /dev/null +++ b/aspnetcore/host-and-deploy/windows-service/sample/wwwroot/css/site.min.css @@ -0,0 +1 @@ +body{padding-top:50px;padding-bottom:20px}h1{font-size:30px}h2{font-size:24px}.body-content{padding-left:15px;padding-right:15px}.panel-body{font-size:16px} diff --git a/aspnetcore/host-and-deploy/windows-service/sample/wwwroot/favicon.ico b/aspnetcore/host-and-deploy/windows-service/sample/wwwroot/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..a3a799985c43bc7309d701b2cad129023377dc71 GIT binary patch literal 32038 zcmeHwX>eTEbtY7aYbrGrkNjgie?1jXjZ#zP%3n{}GObKv$BxI7Sl;Bwl5E+Qtj&t8 z*p|m4DO#HoJC-FyvNnp8NP<{Na0LMnTtO21(rBP}?EAiNjWgeO?z`{3ZoURUQlV2d zY1Pqv{m|X_oO91|?^z!6@@~od!@OH>&BN;>c@O+yUfy5w>LccTKJJ&`-k<%M^Zvi( z<$dKp=jCnNX5Qa+M_%6g|IEv~4R84q9|7E=|Ho(Wz3f-0wPjaRL;W*N^>q%^KGRr7 zxbjSORb_c&eO;oV_DZ7ua!sPH=0c+W;`vzJ#j~-x3uj};50#vqo*0w4!LUqs*UCh9 zvy2S%$#8$K4EOa&e@~aBS65_hc~Mpu=454VT2^KzWqEpBA=ME|O;1cn?8p<+{MKJf zbK#@1wzL44m$k(?85=Obido7=C|xWKe%66$z)NrzRwR>?hK?_bbwT z@Da?lBrBL}Zemo1@!9pYRau&!ld17h{f+UV0sY(R{ET$PBB|-=Nr@l-nY6w8HEAw* zRMIQU`24Jl_IFEPcS=_HdrOP5yf81z_?@M>83Vv65$QFr9nPg(wr`Ke8 zaY4ogdnMA*F7a4Q1_uXadTLUpCk;$ZPRRJ^sMOch;rlbvUGc1R9=u;dr9YANbQ<4Z z#P|Cp9BP$FXNPolgyr1XGt$^lFPF}rmBF5rj1Kh5%dforrP8W}_qJL$2qMBS-#%-|s#BPZBSETsn_EBYcr(W5dq( z@f%}C|iN7)YN`^)h7R?Cg}Do*w-!zwZb9=BMp%Wsh@nb22hA zA{`wa8Q;yz6S)zfo%sl08^GF`9csI9BlGnEy#0^Y3b);M+n<(}6jziM7nhe57a1rj zC@(2ISYBL^UtWChKzVWgf%4LW2Tqg_^7jMw`C$KvU+mcakFjV(BGAW9g%CzSyM;Df z143=mq0oxaK-H;o>F3~zJ<(3-j&?|QBn)WJfP#JR zRuA;`N?L83wQt78QIA$(Z)lGQY9r^SFal;LB^qi`8%8@y+mwcGsf~nv)bBy2S7z~9 z=;X@Gglk)^jpbNz?1;`!J3QUfAOp4U$Uxm5>92iT`mek#$>s`)M>;e4{#%HAAcb^8_Ax%ersk|}# z0bd;ZPu|2}18KtvmIo8`1@H~@2ejwo(5rFS`Z4&O{$$+ch2hC0=06Jh`@p+p8LZzY z&2M~8T6X^*X?yQ$3N5EzRv$(FtSxhW>>ABUyp!{484f8(%C1_y)3D%Qgfl_!sz`LTXOjR&L!zPA0qH_iNS!tY{!^2WfD%uT}P zI<~&?@&))5&hPPHVRl9);TPO>@UI2d!^ksb!$9T96V(F){puTsn(}qt_WXNw4VvHj zf;6A_XCvE`Z@}E-IOaG0rs>K>^=Sr&OgT_p;F@v0VCN0Y$r|Lw1?Wjt`AKK~RT*kJ z2>QPuVgLNcF+XKno;WBv$yj@d_WFJbl*#*V_Cwzo@%3n5%z4g21G*PVZ)wM5$A{klYozmGlB zT@u2+s}=f}25%IA!yNcXUr!!1)z(Nqbhojg0lv@7@0UlvUMT)*r;M$d0-t)Z?B1@qQk()o!4fqvfr_I0r7 zy1(NdkHEj#Yu{K>T#We#b#FD=c1XhS{hdTh9+8gy-vkcdkk*QS@y(xxEMb1w6z<^~ zYcETGfB#ibR#ql0EiD;PR$L&Vrh2uRv5t_$;NxC;>7_S5_OXxsi8udY3BUUdi55Sk zcyKM+PQ9YMA%D1kH1q48OFG(Gbl=FmV;yk8o>k%0$rJ8%-IYsHclnYuTskkaiCGkUlkMY~mx&K}XRlKIW;odWIeuKjtbc^8bBOTqK zjj(ot`_j?A6y_h%vxE9o*ntx#PGrnK7AljD_r58ylE*oy@{IY%+mA^!|2vW_`>`aC{#3`#3;D_$^S^cM zRcF+uTO2sICledvFgNMU@A%M)%8JbSLq{dD|2|2Sg8vvh_uV6*Q?F&rKaV{v_qz&y z`f;stIb?Cb2!Cg7CG91Bhu@D@RaIrq-+o+T2fwFu#|j>lD6ZS9-t^5cx>p|?flqUA z;Cgs#V)O#`Aw4$Kr)L5?|7f4izl!;n0jux}tEW$&&YBXz9o{+~HhoiYDJ`w5BVTl&ARya=M7zdy$FEe}iGBur8XE>rhLj&_yDk5D4n2GJZ07u7%zyAfNtOLn;)M?h*Py-Xtql5aJOtL4U8e|!t? z((sc6&OJXrPdVef^wZV&x=Z&~uA7^ix8rly^rEj?#d&~pQ{HN8Yq|fZ#*bXn-26P^ z5!)xRzYO9{u6vx5@q_{FE4#7BipS#{&J7*>y}lTyV94}dfE%Yk>@@pDe&F7J09(-0|wuI|$of-MRfK51#t@t2+U|*s=W; z!Y&t{dS%!4VEEi$efA!#<<7&04?kB}Soprd8*jYv;-Qj~h~4v>{XX~kjF+@Z7<t?^|i z#>_ag2i-CRAM8Ret^rZt*^K?`G|o>1o(mLkewxyA)38k93`<~4VFI?5VB!kBh%NNU zxb8K(^-MU1ImWQxG~nFB-Un;6n{lQz_FfsW9^H$Xcn{;+W^ZcG$0qLM#eNV=vGE@# z1~k&!h4@T|IiI<47@pS|i?Qcl=XZJL#$JKve;booMqDUYY{(xcdj6STDE=n?;fsS1 ze`h~Q{CT$K{+{t+#*I1=&&-UU8M&}AwAxD-rMa=e!{0gQXP@6azBq9(ji11uJF%@5 zCvV`#*?;ZguQ7o|nH%bm*s&jLej#@B35gy32ZAE0`Pz@#j6R&kN5w{O4~1rhDoU zEBdU)%Nl?8zi|DR((u|gg~r$aLYmGMyK%FO*qLvwxK5+cn*`;O`16c!&&XT{$j~5k zXb^fbh1GT-CI*Nj{-?r7HNg=e3E{6rxuluPXY z5Nm8ktc$o4-^SO0|Es_sp!A$8GVwOX+%)cH<;=u#R#nz;7QsHl;J@a{5NUAmAHq4D zIU5@jT!h?kUp|g~iN*!>jM6K!W5ar0v~fWrSHK@})@6Lh#h)C6F6@)&-+C3(zO! z8+kV|B7LctM3DpI*~EYo>vCj>_?x&H;>y0*vKwE0?vi$CLt zfSJB##P|M2dEUDBPKW=9cY-F;L;h3Fs4E2ERdN#NSL7ctAC z?-}_a{*L@GA7JHJudxtDVA{K5Yh*k(%#x4W7w+^ zcb-+ofbT5ieG+@QG2lx&7!MyE2JWDP@$k`M;0`*d+oQmJ2A^de!3c53HFcfW_Wtv< zKghQ;*FifmI}kE4dc@1y-u;@qs|V75Z^|Q0l0?teobTE8tGl@EB?k#q_wUjypJ*R zyEI=DJ^Z+d*&}B_xoWvs27LtH7972qqMxVFcX9}c&JbeNCXUZM0`nQIkf&C}&skSt z^9fw@b^Hb)!^hE2IJq~~GktG#ZWwWG<`@V&ckVR&r=JAO4YniJewVcG`HF;59}=bf zLyz0uxf6MhuSyH#-^!ZbHxYl^mmBVrx) zyrb8sQ*qBd_WXm9c~Of$&ZP$b^)<~0%nt#7y$1Jg$e}WCK>TeUB{P>|b1FAB?%K7>;XiOfd}JQ`|IP#Vf%kVy zXa4;XFZ+>n;F>uX&3|4zqWK2u3c<>q;tzjsb1;d{u;L$-hq3qe@82(ob<3qom#%`+ z;vzYAs7TIMl_O75BXu|r`Qhc4UT*vN$3Oo0kAC!{f2#HexDy|qUpgTF;k{o6|L>7l z=?`=*LXaow1o;oNNLXsGTrvC)$R&{m=94Tf+2iTT3Y_Or z-!;^0a{kyWtO4vksG_3cyc7HQ0~detf0+2+qxq(e1NS251N}w5iTSrM)`0p8rem!j zZ56hGD=pHI*B+dd)2B`%|9f0goozCSeXPw3 z+58k~sI02Yz#lOneJzYcG)EB0|F+ggC6D|B`6}d0khAK-gz7U3EGT|M_9$ZINqZjwf>P zJCZ=ogSoE`=yV5YXrcTQZx@Un(64*AlLiyxWnCJ9I<5Nc*eK6eV1Mk}ci0*NrJ=t| zCXuJG`#7GBbPceFtFEpl{(lTm`LX=B_!H+& z>$*Hf}}y zkt@nLXFG9%v**s{z&{H4e?aqp%&l#oU8lxUxk2o%K+?aAe6jLojA& z_|J0<-%u^<;NT*%4)n2-OdqfctSl6iCHE?W_Q2zpJken#_xUJlidzs249H=b#g z?}L4-Tnp6)t_5X?_$v)vz`s9@^BME2X@w<>sKZ3=B{%*B$T5Nj%6!-Hr;I!Scj`lH z&2dHFlOISwWJ&S2vf~@I4i~(0*T%OFiuX|eD*nd2utS4$1_JM?zmp>a#CsVy6Er^z zeNNZZDE?R3pM?>~e?H_N`C`hy%m4jb;6L#8=a7l>3eJS2LGgEUxsau-Yh9l~o7=Yh z2mYg3`m5*3Ik|lKQf~euzZlCWzaN&=vHuHtOwK!2@W6)hqq$Zm|7`Nmu%9^F6UH?+ z@2ii+=iJ;ZzhiUKu$QB()nKk3FooI>Jr_IjzY6=qxYy;&mvi7BlQ?t4kRjIhb|2q? zd^K~{-^cxjVSj?!Xs=Da5IHmFzRj!Kzh~b!?`P7c&T9s77VLYB?8_?F zauM^)p;qFG!9PHLfIsnt43UnmV?Wn?Ki7aXSosgq;f?MYUuSIYwOn(5vWhb{f%$pn z4ySN-z}_%7|B);A@PA5k*7kkdr4xZ@s{e9j+9w;*RFm;XPDQwx%~;8iBzSKTIGKO z{53ZZU*OLr@S5=k;?CM^i#zkxs3Sj%z0U`L%q`qM+tP zX$aL;*^g$7UyM2Go+_4A+f)IQcy^G$h2E zb?nT$XlgTEFJI8GN6NQf%-eVn9mPilRqUbT$pN-|;FEjq@Ao&TxpZg=mEgBHB zU@grU;&sfmqlO=6|G3sU;7t8rbK$?X0y_v9$^{X`m4jZ_BR|B|@?ZCLSPPEzz`w1n zP5nA;4(kQFKm%$enjkkBxM%Y}2si&d|62L)U(dCzCGn56HN+i#6|nV-TGIo0;W;`( zW-y=1KF4dp$$mC_|6}pbb>IHoKQeZajXQB>jVR?u`R>%l1o54?6NnS*arpVopdEF; zeC5J3*M0p`*8lif;!irrcjC?(uExejsi~>4wKYwstGY^N@KY}TujLx`S=Cu+T=!dx zKWlPm->I**E{A*q-Z^FFT5$G%7Ij0_*Mo4-y6~RmyTzUB&lfae(WZfO>um}mnsDXPEbau-!13!!xd!qh*{C)6&bz0j1I{>y$D-S)b*)JMCPk!=~KL&6Ngin0p6MCOxF2L_R9t8N!$2Wpced<#`y!F;w zKTi5V_kX&X09wAIJ#anfg9Dhn0s7(C6Nj3S-mVn(i|C6ZAVq0$hE)874co};g z^hR7pe4lU$P;*ggYc4o&UTQC%liCXooIfkI3TNaBV%t~FRr}yHu7kjQ2J*3;e%;iW zvDVCh8=G80KAeyhCuY2LjrC!Od1rvF7h}zszxGV)&!)6ChP5WAjv-zQAMNJIG!JHS zwl?pLxC-V5II#(hQ`l)ZAp&M0xd4%cxmco*MIk?{BD=BK`1vpc}D39|XlV z{c&0oGdDa~TL2FT4lh=~1NL5O-P~0?V2#ie`v^CnANfGUM!b4F=JkCwd7Q`c8Na2q zJGQQk^?6w}Vg9-{|2047((lAV84uN%sK!N2?V(!_1{{v6rdgZl56f0zDMQ+q)jKzzu^ztsVken;=DjAh6G`Cw`Q4G+BjS+n*=KI~^K{W=%t zbD-rN)O4|*Q~@<#@1Vx$E!0W9`B~IZeFn87sHMXD>$M%|Bh93rdGf1lKoX3K651t&nhsl= zXxG|%@8}Bbrlp_u#t*DZX<}_0Yb{A9*1Pd_)LtqNwy6xT4pZrOY{s?N4)pPwT(i#y zT%`lRi8U#Ken4fw>H+N`{f#FF?ZxFlLZg7z7#cr4X>id z{9kUD`d2=w_Zlb{^c`5IOxWCZ1k<0T1D1Z31IU0Q2edsZ1K0xv$pQVYq2KEp&#v#Z z?{m@Lin;*Str(C2sfF^L>{R3cjY`~#)m>Wm$Y|1fzeS0-$(Q^z@} zEO*vlb-^XK9>w&Ef^=Zzo-1AFSP#9zb~X5_+){$(eB4K z8gtW+nl{q+CTh+>v(gWrsP^DB*ge(~Q$AGxJ-eYc1isti%$%nM<_&Ev?%|??PK`$p z{f-PM{Ym8k<$$)(F9)tqzFJ?h&Dk@D?Dt{4CHKJWLs8$zy6+(R)pr@0ur)xY{=uXFFzH_> z-F^tN1y(2hG8V)GpDg%wW0Px_ep~nIjD~*HCSxDi0y`H!`V*~RHs^uQsb1*bK1qGpmd zB1m`Cjw0`nLBF2|umz+a#2X$c?Lj;M?Lj;MUp*d>7j~ayNAyj@SLpeH`)BgRH}byy zyQSat!;U{@O(<<2fp&oQkIy$z`_CQ-)O@RN;QD9T4y|wIJ^%U#(BF%=`i49}j!D-) zkOwPSJaG03SMkE~BzW}b_v>LA&y)EEYO6sbdnTX*$>UF|JhZ&^MSb4}Tgbne_4n+C zwI8U4i~PI>7a3{kVa8|))*%C0|K+bIbmV~a`|G#+`TU#g zXW;bWIcWsQi9c4X*RUDpIfyoPY)2bI-r9)xulm1CJDkQd6u+f)_N=w1ElgEBjprPF z3o?Ly0RVeY_{3~fPVckRMxe2lM8hj!B8F)JO z!`AP6>u>5Y&3o9t0QxBpNE=lJx#NyIbp1gD zzUYBIPYHIv9ngk-Zt~<)62^1Zs1LLYMh@_tP^I7EX-9)Ed0^@y{k65Gp0KRcTmMWw zU|+)qx{#q0SL+4q?Q`i0>COIIF8a0Cf&C`hbMj?LmG9K&iW-?PJt*u)38tTXAP>@R zZL6uH^!RYNq$p>PKz7f-zvg>OKXcZ8h!%Vo@{VUZp|+iUD_xb(N~G|6c#oQK^nHZU zKg#F6<)+`rf~k*Xjjye+syV{bwU2glMMMs-^ss4`bYaVroXzn`YQUd__UlZL_mLs z(vO}k!~(mi|L+(5&;>r<;|OHnbXBE78LruP;{yBxZ6y7K3)nMo-{6PCI7gQi6+rF_ zkPod!Z8n}q46ykrlQS|hVB(}(2Kf7BCZ>Vc;V>ccbk2~NGaf6wGQH@W9&?Zt3v(h*P4xDrN>ex7+jH*+Qg z%^jH$&+*!v{sQ!xkWN4+>|b}qGvEd6ANzgqoVy5Qfws}ef2QqF{iiR5{pT}PS&yjo z>lron#va-p=v;m>WB+XVz|o;UJFdjo5_!RRD|6W{4}A2a#bZv)gS_`b|KsSH)Sd_JIr%<%n06TX&t{&!H#{)?4W9hlJ`R1>FyugOh3=D_{einr zu(Wf`qTkvED+gEULO0I*Hs%f;&=`=X4;N8Ovf28x$A*11`dmfy2=$+PNqX>XcG`h% zJY&A6@&)*WT^rC(Caj}2+|X|6cICm5h0OK0cGB_!wEKFZJU)OQ+TZ1q2bTx9hxnq& z$9ee|f9|0M^)#E&Pr4)f?o&DMM4w>Ksb{hF(0|wh+5_{vPow{V%TFzU2za&gjttNi zIyR9qA56dX52Qbv2aY^g`U7R43-p`#sO1A=KS2aKgfR+Yu^bQ*i-qu z%0mP;Ap)B~zZgO9lG^`325gOf?iUHF{~7jyGC)3L(eL(SQ70VzR~wLN18tnx(Cz2~ zctBl1kI)wAe+cxWHw*NW-d;=pd+>+wd$a@GBju*wFvabSaPtHiT!o#QFC+wBVwYo3s=y;z1jM+M=Fj!FZM>UzpL-eZzOT( zhmZmEfWa=%KE#V3-ZK5#v!Hzd{zc^{ctF~- z>DT-U`}5!fk$aj24`#uGdB7r`>oX5tU|d*b|N3V1lXmv%MGrvE(dXG)^-J*LA>$LE z7kut4`zE)v{@Op|(|@i#c>tM!12FQh?}PfA0`Bp%=%*RiXVzLDXnXtE@4B)5uR}a> zbNU}q+712pIrM`k^odG8dKtG$zwHmQI^c}tfjx5?egx3!e%JRm_64e+>`Ra1IRfLb z1KQ`SxmH{cZfyVS5m(&`{V}Y4j6J{b17`h6KWqZ&hfc(oR zxM%w!$F(mKy05kY&lco3%zvLCxBW+t*rxO+i=qGMvobx0-<7`VUu)ka`){=ew+Ovt zg%52_{&UbkUA8aJPWsk)gYWV4`dnxI%s?7^fGpq{ZQuu=VH{-t7w~K%_E<8`zS;V- zKTho*>;UQQul^1GT^HCt@I-q?)&4!QDgBndn?3sNKYKCQFU4LGKJ$n@Je$&w9@E$X z^p@iJ(v&`1(tq~1zc>0Vow-KR&vm!GUzT?Eqgnc)leZ9p)-Z*C!zqb=-$XG0 z^!8RfuQs5s>Q~qcz92(a_Q+KH?C*vCTr~UdTiR`JGuNH8v(J|FTiSEcPrBpmHRtmd zI2Jng0J=bXK);YY^rM?jzn?~X-Pe`GbAy{D)Y6D&1GY-EBcy%Bq?bKh?A>DD9DD!p z?{q02wno2sraGUkZv5dx+J8)&K$)No43Zr(*S`FEdL!4C)}WE}vJd%{S6-3VUw>Wp z?Aasv`T0^%P$2vE?L+Qhj~qB~K%eW)xH(=b_jU}TLD&BP*Pc9hz@Z=e0nkpLkWl}> z_5J^i(9Z7$(XG9~I3sY)`OGZ#_L06+Dy4E>UstcP-rU@xJ$&rxvo!n1Ao`P~KLU-8 z{zDgN4-&A6N!kPSYbQ&7sLufi`YtE2uN$S?e&5n>Y4(q#|KP!cc1j)T^QrUXMPFaP z_SoYO8S8G}Z$?AL4`;pE?7J5K8yWqy23>cCT2{=-)+A$X^-I9=e!@J@A&-;Ufc)`H}c(VI&;0x zrrGv()5mjP%jXzS{^|29?bLNXS0bC%p!YXI!;O457rjCEEzMkGf~B3$T}dXBO23tP z+Ci>;5UoM?C@bU@f9G1^X3=ly&ZeFH<@|RnOG--A&)fd)AUgjw?%izq{p(KJ`EP0v z2mU)P!+3t@X14DA=E2RR-|p${GZ9ETX=d+kJRZL$nSa0daI@&oUUxnZg0xd_xu>Vz lzF#z5%kSKX?YLH3ll^(hI(_`L*t#Iva2Ede*Z;>H_ \ No newline at end of file diff --git a/aspnetcore/host-and-deploy/windows-service/sample/wwwroot/images/banner2.svg b/aspnetcore/host-and-deploy/windows-service/sample/wwwroot/images/banner2.svg new file mode 100644 index 000000000000..9679c604d00d --- /dev/null +++ b/aspnetcore/host-and-deploy/windows-service/sample/wwwroot/images/banner2.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/aspnetcore/host-and-deploy/windows-service/sample/wwwroot/images/banner3.svg b/aspnetcore/host-and-deploy/windows-service/sample/wwwroot/images/banner3.svg new file mode 100644 index 000000000000..9be2c2503c1a --- /dev/null +++ b/aspnetcore/host-and-deploy/windows-service/sample/wwwroot/images/banner3.svg @@ -0,0 +1 @@ +banner3b \ No newline at end of file diff --git a/aspnetcore/host-and-deploy/windows-service/sample/wwwroot/images/banner4.svg b/aspnetcore/host-and-deploy/windows-service/sample/wwwroot/images/banner4.svg new file mode 100644 index 000000000000..38b3d7cd1f2a --- /dev/null +++ b/aspnetcore/host-and-deploy/windows-service/sample/wwwroot/images/banner4.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/aspnetcore/host-and-deploy/windows-service/sample/wwwroot/js/site.js b/aspnetcore/host-and-deploy/windows-service/sample/wwwroot/js/site.js new file mode 100644 index 000000000000..82ecce7b4a78 --- /dev/null +++ b/aspnetcore/host-and-deploy/windows-service/sample/wwwroot/js/site.js @@ -0,0 +1 @@ +// Write your Javascript code. diff --git a/aspnetcore/host-and-deploy/windows-service/sample/wwwroot/js/site.min.js b/aspnetcore/host-and-deploy/windows-service/sample/wwwroot/js/site.min.js new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/aspnetcore/host-and-deploy/windows-service/sample_snapshot/Program.cs b/aspnetcore/host-and-deploy/windows-service/sample_snapshot/Program.cs new file mode 100644 index 000000000000..8f9cfa64e89b --- /dev/null +++ b/aspnetcore/host-and-deploy/windows-service/sample_snapshot/Program.cs @@ -0,0 +1,104 @@ +#define HandleStopStart // or ServiceOnly ServiceOrConsole +using Microsoft.AspNetCore.Hosting; +using Microsoft.AspNetCore.Hosting.WindowsServices; +using System.Diagnostics; +using System.IO; +using System.Linq; + +namespace AspNetCoreService +{ + public class Program + { +#if ServiceOnly + #region ServiceOnly + public static void Main(string[] args) + { + var pathToExe = Process.GetCurrentProcess().MainModule.FileName; + var pathToContentRoot = Path.GetDirectoryName(pathToExe); + + var host = new WebHostBuilder() + .UseKestrel() + .UseContentRoot(pathToContentRoot) + .UseIISIntegration() + .UseStartup() + .UseApplicationInsights() + .Build(); + + host.RunAsService(); + } + #endregion +#endif +#if ServiceOrConsole +#region ServiceOrConsole + public static void Main(string[] args) + { + bool isService = true; + if (Debugger.IsAttached || args.Contains("--console")) + { + isService = false; + } + + var pathToContentRoot = Directory.GetCurrentDirectory(); + if (isService) + { + var pathToExe = Process.GetCurrentProcess().MainModule.FileName; + pathToContentRoot = Path.GetDirectoryName(pathToExe); + } + + var host = new WebHostBuilder() + .UseKestrel() + .UseContentRoot(pathToContentRoot) + .UseIISIntegration() + .UseStartup() + .UseApplicationInsights() + .Build(); + + if (isService) + { + host.RunAsService(); + } + else + { + host.Run(); + } + } +#endregion +#endif +#if HandleStopStart +#region HandleStopStart + public static void Main(string[] args) + { + bool isService = true; + if (Debugger.IsAttached || args.Contains("--console")) + { + isService = false; + } + + var pathToContentRoot = Directory.GetCurrentDirectory(); + if (isService) + { + var pathToExe = Process.GetCurrentProcess().MainModule.FileName; + pathToContentRoot = Path.GetDirectoryName(pathToExe); + } + + var host = new WebHostBuilder() + .UseKestrel() + .UseContentRoot(pathToContentRoot) + .UseIISIntegration() + .UseStartup() + .UseApplicationInsights() + .Build(); + + if (isService) + { + host.RunAsCustomService(); + } + else + { + host.Run(); + } + } +#endregion +#endif + } +} From 9b3891b85c964e63a50abfcb31edebaac983808e Mon Sep 17 00:00:00 2001 From: Luke Latham <1622880+guardrex@users.noreply.github.com> Date: Tue, 30 Jan 2018 19:37:32 -0600 Subject: [PATCH 2/2] React to feedback --- aspnetcore/host-and-deploy/windows-service.md | 6 +++--- aspnetcore/host-and-deploy/windows-service/sample/README.md | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/aspnetcore/host-and-deploy/windows-service.md b/aspnetcore/host-and-deploy/windows-service.md index 88479fb50b5a..44aadc6d2cce 100644 --- a/aspnetcore/host-and-deploy/windows-service.md +++ b/aspnetcore/host-and-deploy/windows-service.md @@ -17,7 +17,7 @@ By [Tom Dykstra](https://github.com/tdykstra) The recommended way to host an ASP.NET Core app on Windows without using IIS is to run it in a [Windows Service](/dotnet/framework/windows-services/introduction-to-windows-service-applications). When hosted as a Windows Service, the app can automatically start after reboots and crashes without requiring human intervention. -[View or download sample code](https://github.com/aspnet/Docs/tree/master/aspnetcore/host-and-deploy/windows-service/sample) ([how to download](xref:tutorials/index#how-to-download-a-sample)). For instrucitons on how to run the sample app, see the sample's *README.md* file. +[View or download sample code](https://github.com/aspnet/Docs/tree/master/aspnetcore/host-and-deploy/windows-service/sample) ([how to download](xref:tutorials/index#how-to-download-a-sample)). For instructions on how to run the sample app, see the sample's *README.md* file. ## Prerequisites @@ -55,7 +55,7 @@ This section explains the minimum changes required to set up an existing ASP.NET 1. Test by creating and starting the service. - Open an administrator command prompt window to use the [sc.exe](https://technet.microsoft.com/library/bb490995) command-line tool to create and start a service. If the service is named MyService, published to `c:\svc`, and named AspNetCoreService, the commands are: + Open a command shell with administrative privileges to use the [sc.exe](https://technet.microsoft.com/library/bb490995) command-line tool to create and start a service. If the service is named MyService, published to `c:\svc`, and named AspNetCoreService, the commands are: ```console sc create MyService binPath="c:\svc\aspnetcoreservice.exe" @@ -96,7 +96,7 @@ To handle `OnStarting`, `OnStarted`, and `OnStopping` events, make the following [!code-csharp[](windows-service/sample/WebHostServiceExtensions.cs?name=ExtensionsClass)] -1. In `Program.Main`, call the new extension method,`RunAsCustomService`, instead of `RunAsService`: +1. In `Program.Main`, call the new extension method, `RunAsCustomService`, instead of `RunAsService`: # [ASP.NET Core 2.x](#tab/aspnetcore2x) diff --git a/aspnetcore/host-and-deploy/windows-service/sample/README.md b/aspnetcore/host-and-deploy/windows-service/sample/README.md index 311a137195fa..7956175aeff1 100644 --- a/aspnetcore/host-and-deploy/windows-service/sample/README.md +++ b/aspnetcore/host-and-deploy/windows-service/sample/README.md @@ -12,7 +12,7 @@ To run the app in a service, perform the following steps: 1. Publish the app to the folder with `dotnet publish --configuration Release --output c:\\svc`. The command will move the app's assets to the folder, including the required `appsettings.json` file and the `wwwroot` folder with its contents. -1. Open an **administrator** command prompt. +1. Open an **administrator** command shell. 1. Execute the following commands: