AspNetCore.Docs/aspnetcore/host-and-deploy/windows-service.md

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:

  1. In the project file:

    1. 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

    2. Add a package reference for Microsoft.AspNetCore.Hosting.WindowsServices.

  2. 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"

      [!code-csharp]

      ::: moniker-end

      ::: moniker range="< aspnetcore-2.0"

      [!code-csharp]

      ::: moniker-end

  3. 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
    
  4. 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:

    1. 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.
    2. 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 to binPath.
  5. 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.

  6. 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
    
  7. 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 to https://localhost:5001 when using HTTPS Redirection Middleware).

    For the sample app service, browse the app at http://localhost:5000.

  8. Stop the service with the sc stop <SERVICE_NAME> command.

    The following command stops the sample app service:

    sc stop MyService
    
  9. 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"

[!code-csharp]

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 from Main into CreateWebHostBuilder because the signature of CreateWebHostBuilder must be CreateWebHostBuilder(string[]) in order for integration testing to work properly.

::: moniker-end

::: moniker range="< aspnetcore-2.0"

[!code-csharp]

::: moniker-end

Handle stopping and starting events

To handle OnStarting, OnStarted, and OnStopping events, make the following additional changes:

  1. Create a class that derives from WebHostService:

    [!code-csharp]

  2. Create an extension method for IWebHost that passes the custom WebHostService to ServiceBase.Run:

    [!code-csharp]

  3. In Program.Main, call the new extension method, RunAsCustomService, instead of RunAsService:

    ::: moniker range=">= aspnetcore-2.0"

    [!code-csharp]

    [!NOTE] isService isn't passed from Main into CreateWebHostBuilder because the signature of CreateWebHostBuilder must be CreateWebHostBuilder(string[]) in order for integration testing to work properly.

    ::: moniker-end

    ::: moniker range="< aspnetcore-2.0"

    [!code-csharp]

    ::: moniker-end

If the custom WebHostService code requires a service from dependency injection (such as a logger), obtain it from the IWebHost.Services property:

[!code-csharp]

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 the binPath argument when the service is created. Instead of using Directory.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