Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
100 changes: 50 additions & 50 deletions aspnetcore/host-and-deploy/windows-service.md
Original file line number Diff line number Diff line change
@@ -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
Expand All @@ -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 instructions 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 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 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/)
Original file line number Diff line number Diff line change
@@ -1,21 +1,24 @@
<Project Sdk="Microsoft.NET.Sdk.Web">

<PropertyGroup>
<TargetFramework>net452</TargetFramework>
<RuntimeIdentifier>win7-x86</RuntimeIdentifier>
<TargetFramework>net461</TargetFramework>
<RuntimeIdentifier>win7-x64</RuntimeIdentifier>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Microsoft.ApplicationInsights.AspNetCore" Version="2.0.0" />
<PackageReference Include="Microsoft.AspNetCore" Version="1.1.1" />
<PackageReference Include="Microsoft.AspNetCore.Hosting.WindowsServices" Version="1.1.1" />
<PackageReference Include="Microsoft.AspNetCore.Mvc" Version="1.1.2" />
<PackageReference Include="Microsoft.AspNetCore.StaticFiles" Version="1.1.1" />
<PackageReference Include="Microsoft.Extensions.Logging.Debug" Version="1.1.1" />
<PackageReference Include="Microsoft.VisualStudio.Web.BrowserLink" Version="1.1.0" />
<PackageReference Include="Microsoft.ApplicationInsights.AspNetCore" Version="2.1.1" />
<PackageReference Include="Microsoft.AspNetCore" Version="2.0.1" />
<PackageReference Include="Microsoft.AspNetCore.Hosting.WindowsServices" Version="2.0.1" />
<PackageReference Include="Microsoft.AspNetCore.Mvc" Version="2.0.2" />
<PackageReference Include="Microsoft.AspNetCore.StaticFiles" Version="2.0.1" />
<PackageReference Include="Microsoft.Extensions.Logging.Debug" Version="2.0.0" />
<PackageReference Include="Microsoft.VisualStudio.Web.BrowserLink" Version="2.0.1" />
</ItemGroup>

<ItemGroup>
<DotNetCliToolReference Include="Microsoft.VisualStudio.Web.CodeGeneration.Tools" Version="1.0.0" />
<DotNetCliToolReference Include="Microsoft.VisualStudio.Web.CodeGeneration.Tools" Version="2.0.2" />
</ItemGroup>

<ItemGroup>
<Compile Update="CustomWebHostService.cs">
<SubType>Component</SubType>
Expand Down
40 changes: 17 additions & 23 deletions aspnetcore/host-and-deploy/windows-service/sample/Program.cs
Original file line number Diff line number Diff line change
@@ -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
{
Expand All @@ -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<Startup>()
.UseApplicationInsights()
.Build();
var host = WebHost.CreateDefaultBuilder(args)
.UseContentRoot(pathToContentRoot)
.UseStartup<Startup>()
.UseApplicationInsights()
.Build();

host.RunAsService();
}
Expand All @@ -45,13 +43,11 @@ public static void Main(string[] args)
pathToContentRoot = Path.GetDirectoryName(pathToExe);
}

var host = new WebHostBuilder()
.UseKestrel()
.UseContentRoot(pathToContentRoot)
.UseIISIntegration()
.UseStartup<Startup>()
.UseApplicationInsights()
.Build();
var host = WebHost.CreateDefaultBuilder(args)
.UseContentRoot(pathToContentRoot)
.UseStartup<Startup>()
.UseApplicationInsights()
.Build();

if (isService)
{
Expand Down Expand Up @@ -81,13 +77,11 @@ public static void Main(string[] args)
pathToContentRoot = Path.GetDirectoryName(pathToExe);
}

var host = new WebHostBuilder()
.UseKestrel()
.UseContentRoot(pathToContentRoot)
.UseIISIntegration()
.UseStartup<Startup>()
.UseApplicationInsights()
.Build();
var host = WebHost.CreateDefaultBuilder(args)
.UseContentRoot(pathToContentRoot)
.UseStartup<Startup>()
.UseApplicationInsights()
.Build();

if (isService)
{
Expand Down
43 changes: 43 additions & 0 deletions aspnetcore/host-and-deploy/windows-service/sample/README.md
Original file line number Diff line number Diff line change
@@ -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 shell.

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<Microsoft.Extensions.Configuration.IConfigurationProvider>)
at Microsoft.Extensions.Configuration.ConfigurationBuilder.Build()
...
```
Original file line number Diff line number Diff line change
@@ -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;
}
Original file line number Diff line number Diff line change
@@ -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}
Binary file not shown.
Loading