11 KiB
title | author | description | ms.author | ms.custom | ms.date | uid |
---|---|---|---|---|---|---|
Host ASP.NET Core in a Windows Service | guardrex | Learn how to host an ASP.NET Core app in a Windows Service. | tdykstra | mvc | 06/04/2018 | host-and-deploy/windows-service |
Host ASP.NET Core in a Windows Service
By Luke Latham and Tom Dykstra
An ASP.NET Core app can be hosted on Windows without using IIS as a Windows Service. When hosted as a Windows Service, the app can automatically start after reboots and crashes without requiring human intervention.
View or download sample code (how to download)
Get started
The following minimum changes are required to set up an existing ASP.NET Core project to run in a service:
-
In the project file:
-
Confirm the presence of the runtime identifier or add it to the <PropertyGroup> that contains the target framework:
::: moniker range=">= aspnetcore-2.1"
<PropertyGroup> <TargetFramework>netcoreapp2.1</TargetFramework> <RuntimeIdentifier>win7-x64</RuntimeIdentifier> </PropertyGroup>
::: moniker-end
::: moniker range="= aspnetcore-2.0"
<PropertyGroup> <TargetFramework>netcoreapp2.0</TargetFramework> <RuntimeIdentifier>win7-x64</RuntimeIdentifier> </PropertyGroup>
::: moniker-end
::: moniker range="< aspnetcore-2.0"
<PropertyGroup> <TargetFramework>netcoreapp1.1</TargetFramework> <RuntimeIdentifier>win7-x64</RuntimeIdentifier> </PropertyGroup>
::: moniker-end
-
Add a package reference for Microsoft.AspNetCore.Hosting.WindowsServices.
-
-
Make the following changes in
Program.Main
:-
Call host.RunAsService instead of
host.Run
. -
Call UseContentRoot and use a path to the app's published location instead of
Directory.GetCurrentDirectory()
.::: moniker range=">= aspnetcore-2.0"
::: moniker-end
::: moniker range="< aspnetcore-2.0"
::: moniker-end
-
-
Publish the app. Use dotnet publish or a Visual Studio publish profile. When using a Visual Studio, select the FolderProfile.
To publish the sample app from the command line, run the following command in a console window from the project folder:
dotnet publish --configuration Release
-
Use the sc.exe command-line tool to create the service. The
binPath
value is the path to the app's executable, which includes the executable file name. The space between the equal sign and the quote character at the start of the path is required.sc create <SERVICE_NAME> binPath= "<PATH_TO_SERVICE_EXECUTABLE>"
For a service published in the project folder, use the path to the publish folder to create the service. In the following example:
- The project resides in the
c:\my_services\AspNetCoreService
folder. - The project is published in
Release
configuration. - The Target Framework Moniker (TFM) is
netcoreapp2.1
. - The Runtime Identifer (RID) is
win7-x64
. - The app executable is named AspNetCoreService.exe.
- The service is named MyService.
Example:
sc create MyService binPath= "c:\my_services\AspNetCoreService\bin\Release\netcoreapp2.1\win7-x64\publish\AspNetCoreService.exe"
[!IMPORTANT] Make sure the space is present between the
binPath=
argument and its value.To publish and start the service from a different folder:
- Use the --output <OUTPUT_DIRECTORY> option on the
dotnet publish
command. If using Visual Studio, configure the Target Location in the FolderProfile publish property page before selecting the Publish button. - Create the service with the
sc.exe
command using the output folder path. Include the name of the service's executable in the path provided tobinPath
.
- The project resides in the
-
Start the service with the
sc start <SERVICE_NAME>
command.To start the sample app service, use the following command:
sc start MyService
The command takes a few seconds to start the service.
-
The
sc query <SERVICE_NAME>
command can be used to check the status of the service to determine its status:START_PENDING
RUNNING
STOP_PENDING
STOPPED
Use the following command to check the status of the sample app service:
sc query MyService
-
When the service is in the
RUNNING
state and if the service is a web app, browse the app at its path (by default,http://localhost:5000
, which redirects tohttps://localhost:5001
when using HTTPS Redirection Middleware).For the sample app service, browse the app at
http://localhost:5000
. -
Stop the service with the
sc stop <SERVICE_NAME>
command.The following command stops the sample app service:
sc stop MyService
-
After a short delay to stop a service, uninstall the service with the
sc delete <SERVICE_NAME>
command.Check the status of the sample app service:
sc query MyService
When the sample app service is in the
STOPPED
state, use the following command to uninstall the sample app service:sc delete MyService
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 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:
::: moniker range=">= aspnetcore-2.0"
Because ASP.NET Core configuration requires name-value pairs for command-line arguments, the --console
switch is removed before the arguments are passed to CreateDefaultBuilder.
[!NOTE]
isService
isn't passed fromMain
intoCreateWebHostBuilder
because the signature ofCreateWebHostBuilder
must beCreateWebHostBuilder(string[])
in order for integration testing to work properly.
::: moniker-end
::: moniker range="< aspnetcore-2.0"
::: moniker-end
Handle stopping and starting events
To handle OnStarting, OnStarted, and OnStopping events, make the following additional changes:
-
Create a class that derives from WebHostService:
-
Create an extension method for IWebHost that passes the custom
WebHostService
to ServiceBase.Run: -
In
Program.Main
, call the new extension method,RunAsCustomService
, instead of RunAsService:::: moniker range=">= aspnetcore-2.0"
[!NOTE]
isService
isn't passed fromMain
intoCreateWebHostBuilder
because the signature ofCreateWebHostBuilder
must beCreateWebHostBuilder(string[])
in order for integration testing to work properly.::: moniker-end
::: moniker range="< aspnetcore-2.0"
::: moniker-end
If the custom WebHostService
code requires a service from dependency injection (such as a logger), obtain it from the IWebHost.Services property:
Proxy server and load balancer scenarios
Services that interact with requests from the Internet or a corporate network and are behind a proxy or load balancer might require additional configuration. For more information, see xref:host-and-deploy/proxy-load-balancer.
Configure HTTPS
Specify a Kestrel server HTTPS endpoint configuration.
Current directory and content root
The current working directory returned by calling Directory.GetCurrentDirectory()
for a Windows Service is the C:\WINDOWS\system32 folder. The system32 folder isn't a suitable location to store a service's files (for example, settings files). Use one of the following approaches to maintain and access a service's assets and settings files with FileConfigurationExtensions.SetBasePath when using an IConfigurationBuilder:
- Use the content root path. The
IHostingEnvironment.ContentRootPath
is the same path provided to thebinPath
argument when the service is created. Instead of usingDirectory.GetCurrentDirectory()
to create paths to settings files, use the content root path and maintain the files in the app's content root. - Store the files in a suitable location on disk. Specify an absolute path with
SetBasePath
to the folder containing the files.
Additional resources
- Kestrel endpoint configuration (includes HTTPS configuration and SNI support)
- xref:fundamentals/host/web-host