Windows 서비스에서 ASP.NET Core 응용 프로그램 호스트Host an ASP.NET Core app in a Windows Service

으로 Tom DykstraBy Tom Dykstra

IIS를 사용 하지 않는 경우 Windows에서 ASP.NET Core 응용 프로그램을 호스트 하는 권장된 방법은 실행 하는 것는 Windows 서비스합니다.The recommended way to host an ASP.NET Core app on Windows when you don't use IIS is to run it in a Windows Service. 이런 방식으로 시작할 수 있습니다 자동으로 다시 부팅 하 고 충돌 후 다른 사용자가 로그인 할 때까지 기다리지 않고 합니다.That way it can automatically start after reboots and crashes, without waiting for someone to log in.

보거나 다운로드 샘플 코드 (다운로드 하는 방법을).View or download sample code (how to download). 참조는 다음 단계 실행 하는 방법에 대 한 지침은 섹션.See the Next Steps section for instructions on how to run it.

필수 구성 요소Prerequisites

  • 앱을.NET Framework 런타임에 실행 해야 합니다.The app must run on the .NET Framework runtime. .csproj 파일,이 대 한 적절 한 값을 지정 TargetFrameworkRuntimeIdentifier합니다.In the .csproj file, specify appropriate values for TargetFramework and RuntimeIdentifier. 예를 들면 다음과 같습니다.Here's an example:

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

    Visual Studio에서 프로젝트를 만들 때 사용 된 ASP.NET Core 응용 프로그램 (.NET Framework) 서식 파일입니다.When creating a project in Visual Studio, use the ASP.NET Core Application (.NET Framework) template.

  • 응용 프로그램 요청 (뿐 아니라 내부 네트워크)에서 인터넷을 통해을 발생 사용 해야 합니다는 WebListener 웹 서버 대신 Kestrel합니다.If the app will get requests from the internet (not just from an internal network), it must use the WebListener web server rather than Kestrel. Kestrel은 가장자리 배포에 대 한 IIS 함께 사용 해야 합니다.Kestrel must be used with IIS for edge deployments. 자세한 내용은 Kestrel를 역방향 프록시와 함께 사용할 경우를 참조하세요.For more information, see When to use Kestrel with a reverse proxy.

시작Getting started

이 섹션에서는 서비스에서 실행 되도록 기존 ASP.NET Core 프로젝트를 설정 하는 데 필요한 최소한의 내용을 설명 합니다.This section explains the minimum changes required to set up an existing ASP.NET Core project to run in a service.

  • NuGet 패키지 설치 Microsoft.AspNetCore.Hosting.WindowsServices합니다.Install the NuGet package Microsoft.AspNetCore.Hosting.WindowsServices.

  • 다음과 같이 변경 Program.Main:Make the following changes in Program.Main:

    • 호출 host.RunAsService 대신 host.Run합니다.Call host.RunAsService instead of host.Run.

    • 코드가 호출 UseContentRoot, 대신 게시 위치에 경로 사용 합니다.Directory.GetCurrentDirectory()If your 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 = new WebHostBuilder()
        .UseKestrel()
        .UseContentRoot(pathToContentRoot)
        .UseIISIntegration()
        .UseStartup<Startup>()
        .UseApplicationInsights()
        .Build();
    
        host.RunAsService();
    }
    
  • 폴더에 응용 프로그램을 게시 합니다.Publish the application to a folder.

    사용 하 여 dotnet 게시 또는 Visual Studio 게시 프로필 폴더에 게시 하는 합니다.Use dotnet publish or a Visual Studio publish profile that publishes to a folder.

  • 만들고 서비스를 시작 하 여 테스트 합니다.Test by creating and starting the service.

    사용 하려면 관리자 명령 프롬프트 창을 엽니다는 sc.exe 명령줄 도구를 만들고 서비스를 시작 합니다.Open an administrator command prompt window to use the sc.exe command-line tool to create and start a service.

    앱을 게시 MyService 서비스에 이름을 지정할 경우 c:\svc, 및 앱 자체가 AspNetCoreService 라는, 명령은 다음과 같습니다.If you name your service MyService, you publish your app to c:\svc, and the app itself is named AspNetCoreService, the commands would look like this:

    sc create MyService binPath="C:\Svc\AspNetCoreService.exe"
    sc start MyService
    

    binPath 값은 실행 파일 이름 자체를 포함 하 여 앱의 실행 파일의 경로입니다.The binPath value is the path to your app's executable, including the executable filename itself.

    콘솔 창에서 만들고 시작 예제

    이러한 명령은 완료 되 면 콘솔 응용 프로그램으로 실행 하는 경우와 같은 경로를 찾아볼 수 있습니다 (기본적으로 http://localhost:5000)When these commands finish, you can browse to the same path as when you run as a console app (by default, http://localhost:5000)

    서비스에서 실행

서비스 외부에서 실행 하는 방법을 제공합니다Provide a way to run outside of a service

테스트 하 고 호출 하는 코드를 추가 하는 일반적인 되기 때문에 외부 서비스를 실행 하는 경우 디버깅할 쉽게 host.RunAsService 특정 조건 에서만.It's easier to test and debug when you're running outside of a service, so it's customary to add code that calls host.RunAsService only under certain conditions. 예를 들어 실행할 수 있습니다는 콘솔 응용 프로그램으로 발생 하는 경우는 --console 명령줄 인수나는 디버거가 연결 됩니다.For example, you could run as a console app if you get a --console command-line argument or if the debugger is attached.

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<Startup>()
    .UseApplicationInsights()
    .Build();

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

중지 및 시작 이벤트를 처리 합니다.Handle stopping and starting events

처리 하려는 경우 OnStarting, OnStarted, 및 OnStopping 이벤트를 다음과 같이 변경 추가:If you want to handle OnStarting, OnStarted, and OnStopping events, make the following additional changes:

  • 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();
        }
    }
    
  • 에 대 한 확장 메서드를 만들어 IWebHost 사용자 지정을 통과 하 WebHostServiceServiceBase.Run합니다.Create an extension method for IWebHost that passes your custom WebHostService to ServiceBase.Run.

    public static class WebHostServiceExtensions
    {
        public static void RunAsCustomService(this IWebHost host)
        {
            var webHostService = new CustomWebHostService(host);
            ServiceBase.Run(webHostService);
        }
    }
    
  • Program.Main 대신 새 확장 메서드를 호출 하는 변경 host.RunAsService합니다.In Program.Main change call the new extension method instead of host.RunAsService.

    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<Startup>()
        .UseApplicationInsights()
        .Build();
    
        if (isService)
        {
            host.RunAsCustomService();
        }
        else
        {
            host.Run();
        }
    }
    

하는 경우 사용자 지정 WebHostService 종속성 주입 (예:로 거)에서 서비스 하는 데 필요한 코드에서 가져올 수 있습니다는 Services 속성 IWebHost합니다.If your custom WebHostService code needs to get a service from dependency injection (such as a logger), you can get 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();
    }
}

다음 단계Next steps

샘플 응용 프로그램 이 함께 제공 되는 문서는 이전 코드 예제에서와 같이 수정 된 간단한 MVC 웹 응용 프로그램입니다.The sample application 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:

  • 에 게시 c:\svc합니다.Publish to c:\svc.

  • 관리자 창을 엽니다.Open an administrator window.

  • 다음 명령을 입력 합니다.Enter the following commands:

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

오류 메시지에 액세스할 수 있도록 하는 빠른 방법을 같은 로깅 공급자를 추가 하는 응용 프로그램은 서비스에서 실행 하는 경우 예상 대로 최대 시작 되지 않으면는 Windows 이벤트 로그 공급자합니다.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.

승인Acknowledgments

이미 게시 된 원본의 도움을 받아가이 문서의 작성 되었습니다.This article was written with the help of sources that were already published. 시작와 그 중 가장 유용한 이러한 다음과 같았습니다.The earliest and most useful of them were these: