Hospedar o ASP.NET Core em um serviço WindowsHost ASP.NET Core in a Windows Service

Por Tom DykstraBy Tom Dykstra

A maneira recomendada de hospedar um aplicativo ASP.NET Core no Windows sem usar o IIS é executá-lo em um serviço Windows.The recommended way to host an ASP.NET Core app on Windows without using IIS is to run it in a Windows Service. Quando hospedado como um serviço Windows, o aplicativo pode iniciar automaticamente após reinicializações e falhas, sem exigir intervenção humana.When hosted as a Windows Service, the app can automatically start after reboots and crashes without requiring human intervention.

Exibir ou baixar um código de exemplo (como baixar).View or download sample code (how to download). Para obter instruções sobre como executar o aplicativo de exemplo, confira o arquivo README.md do exemplo.For instructions on how to run the sample app, see the sample's README.md file.

Pré-requisitosPrerequisites

  • O aplicativo deve ser executado no tempo de execução do .NET Framework.The app must run on the .NET Framework runtime. No arquivo .csproj, especifique os valores apropriados para TargetFramework e RuntimeIdentifier.In the .csproj file, specify appropriate values for TargetFramework and RuntimeIdentifier. Veja um exemplo:Here's an example:

    <PropertyGroup>
      <TargetFramework>netcoreapp2.1</TargetFramework>
      <RuntimeIdentifier>win7-x64</RuntimeIdentifier>
    </PropertyGroup>
    

    Ao criar um projeto no Visual Studio, use o modelo Aplicativo ASP.NET Core (.NET Framework).When creating a project in Visual Studio, use the ASP.NET Core Application (.NET Framework) template.

  • Se o aplicativo recebe solicitações da Internet (não apenas de uma rede interna), ele deve usar o servidor Web HTTP.sys (anteriormente conhecido como WebListener para aplicativos do ASP.NET Core 1.x) em vez do Kestrel.If the app receives requests from the Internet (not just from an internal network), it must use the HTTP.sys web server (formerly known as WebListener for ASP.NET Core 1.x apps) rather than Kestrel. O IIS é recomendado para uso como um servidor proxy reverso com o Kestrel para implantações de borda.IIS is recommended for use as a reverse proxy server with Kestrel for edge deployments. Para obter mais informações, consulte Quando usar Kestrel com um proxy reverso.For more information, see When to use Kestrel with a reverse proxy.

IntroduçãoGet started

Esta seção explica as alterações mínimas necessárias para configurar um projeto existente do ASP.NET Core para executar em um serviço.This section explains the minimum changes required to set up an existing ASP.NET Core project to run in a service.

  1. Instale o pacote NuGet Microsoft.AspNetCore.Hosting.WindowsServices.Install the NuGet package Microsoft.AspNetCore.Hosting.WindowsServices.

  2. Faça as seguintes alterações em Program.Main:Make the following changes in Program.Main:

    • Chame host.RunAsService em vez de host.Run.Call host.RunAsService instead of host.Run.

    • Se o código chama UseContentRoot, use um caminho para o local de publicação em vez de Directory.GetCurrentDirectory().If the code calls UseContentRoot, use a path to the publish location instead of Directory.GetCurrentDirectory().

    public static void Main(string[] args)
    {
        var pathToExe = Process.GetCurrentProcess().MainModule.FileName;
        var pathToContentRoot = Path.GetDirectoryName(pathToExe);
    
        var host = WebHost.CreateDefaultBuilder(args)
            .UseContentRoot(pathToContentRoot)
            .UseStartup<Startup>()
            .Build();
    
        host.RunAsService();
    }
    

  1. Publique o aplicativo em uma pasta.Publish the app to a folder. Use dotnet publish ou um perfil de publicação do Visual Studio que publica para uma pasta.Use dotnet publish or a Visual Studio publish profile that publishes to a folder.

  2. Teste criando e iniciando o serviço.Test by creating and starting the service.

    Abra um shell de comando com privilégios administrativos para usar a ferramenta de linha de comando sc.exe para criar e iniciar um serviço.Open a command shell with administrative privileges to use the sc.exe command-line tool to create and start a service. Se o serviço é nomeado MyService, publicado para c:\svc e denominado AspNetCoreService, os comandos são:If the service is named MyService, published to c:\svc, and named AspNetCoreService, the commands are:

    sc create MyService binPath="c:\svc\aspnetcoreservice.exe"
    sc start MyService
    

    O valor binPath é o caminho para o executável do aplicativo, que inclui o nome do arquivo executável.The binPath value is the path to the app's executable, which includes the executable file name.

    Exemplo de criação e início de janela do console

    Quando terminar desses comandos, navegue até o mesmo caminho usado ao executar como um aplicativo de console (por padrão, http://localhost:5000):When these commands finish, browse to the same path as when running as a console app (by default, http://localhost:5000):

    Executar em um serviço

Fornecer uma maneira de executar fora de um serviçoProvide a way to run outside of a service

É mais fácil testar e depurar ao executar fora de um serviço, então é comum adicionar código que chama RunAsService apenas em determinadas condições.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. Por exemplo, o aplicativo pode ser executado como um aplicativo de console com um argumento de linha de comando --console ou se o depurador está anexado:For example, the app can run as a console app with a --console command-line argument or if the debugger is attached:

public static void Main(string[] args)
{
    var 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 webHostArgs = args.Where(arg => arg != "--console").ToArray();

    var host = WebHost.CreateDefaultBuilder(webHostArgs)
        .UseContentRoot(pathToContentRoot)
        .UseStartup<Startup>()
        .Build();

    if (isService)
    {
        host.RunAsService();
    }
    else
    {
        host.Run();
    }
}

Manipular eventos de início e de paradaHandle stopping and starting events

Para manipular eventos OnStarting, OnStarted e OnStopping, faça as seguintes alterações adicionais:To handle OnStarting, OnStarted, and OnStopping events, make the following additional changes:

  1. Crie uma classe que deriva de WebHostService:Create a class that derives from WebHostService:

    internal class CustomWebHostService : WebHostService
    {
        public CustomWebHostService(IWebHost host) : base(host)
        {
        }
    
        protected override void OnStarting(string[] args)
        {
            base.OnStarting(args);
        }
    
        protected override void OnStarted()
        {
            base.OnStarted();
        }
    
        protected override void OnStopping()
        {
            base.OnStopping();
        }
    }
    
  2. Criar um método de extensão para IWebHost que passa o WebHostService personalizado para ServiceBase.Run:Create an extension method for IWebHost that passes the custom WebHostService to ServiceBase.Run:

    public static class WebHostServiceExtensions
    {
        public static void RunAsCustomService(this IWebHost host)
        {
            var webHostService = new CustomWebHostService(host);
            ServiceBase.Run(webHostService);
        }
    }
    
  3. Em Program.Main, chame o novo método de extensão, RunAsCustomService, em vez de RunAsService:In Program.Main, call the new extension method, RunAsCustomService, instead of RunAsService:

    public static void Main(string[] args)
    {
        var 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 webHostArgs = args.Where(arg => arg != "--console").ToArray();
    
        var host = WebHost.CreateDefaultBuilder(args)
            .UseContentRoot(pathToContentRoot)
            .UseStartup<Startup>()
            .Build();
    
        if (isService)
        {
            host.RunAsCustomService();
        }
        else
        {
            host.Run();
        }
    }
    

Se o código WebHostService personalizado requer um serviço de injeção de dependência (como um agente), obtenha-o da propriedade Services de IWebHost:If the custom WebHostService code requires a service from dependency injection (such as a logger), obtain it from the Services property of IWebHost:

internal class CustomWebHostService : WebHostService
{
    private ILogger _logger;

    public CustomWebHostService(IWebHost host) : base(host)
    {
        _logger = host.Services.GetRequiredService<ILogger<CustomWebHostService>>();
    }

    protected override void OnStarting(string[] args)
    {
        _logger.LogDebug("OnStarting method called.");
        base.OnStarting(args);
    }

    protected override void OnStarted()
    {
        _logger.LogDebug("OnStarted method called.");
        base.OnStarted();
    }

    protected override void OnStopping()
    {
        _logger.LogDebug("OnStopping method called.");
        base.OnStopping();
    }
}

Servidor proxy e cenários de balanceador de cargaProxy server and load balancer scenarios

Serviços que interagem com solicitações da Internet ou de uma rede corporativa e estão atrás de um proxy ou de um balanceador de carga podem exigir configuração adicional.Services that interact with requests from the Internet or a corporate network and are behind a proxy or load balancer might require additional configuration. Para obter mais informações, veja Configurar o ASP.NET Core para trabalhar com servidores proxy e balanceadores de carga.For more information, see Configure ASP.NET Core to work with proxy servers and load balancers.

AgradecimentosAcknowledgments

Este artigo foi escrito com a ajuda das fontes publicadas:This article was written with the help of published sources: