将 ASP.NET Core 作为 Windows 服务托管 [英] Hosting ASP.NET Core as Windows service

查看:36
本文介绍了将 ASP.NET Core 作为 Windows 服务托管的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

当我在 RC2 中得到它时,它支持在 Windows 服务中托管应用程序.我尝试在一个简单的 web api 项目上对其进行测试(使用 .NET Framework 4.6.1).

As I get it in RC2 there's a support for hosting applications within Windows Services. I tried to test it on a simple web api project (using .NET Framework 4.6.1).

这是我的 Program.cs 代码:

Here's my Program.cs code:

using System;
using System.IO;
using System.Linq;
using System.ServiceProcess;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Hosting.WindowsServices;

namespace WebApplication4
{
  public class Program : ServiceBase
  {
    public static void Main(string[] args)
    {
      if (args.Contains("--windows-service"))
      {
        Run(new Program());
        return;
      }

      var program = new Program();
      program.OnStart(null);
      Console.ReadLine();
      program.OnStop();
    }

    protected override void OnStart(string[] args)
    {
      var host = new WebHostBuilder()
      .UseKestrel()
      .UseContentRoot(Directory.GetCurrentDirectory())      
      .UseStartup<Startup>()
      .Build();

      host.RunAsService();
    }

    protected override void OnStop() {}
  }
}

所有其他内容基本上都来自 .NET Core 模板(尽管我将框架更改为 net461 并在 project.json 中添加了一些依赖项).

All the other stuff are basically from .NET Core template (though I changed framework to net461 and added some dependencies in project.json).

在使用 dotnet publish 发布并使用 sc create 创建 Windows 服务后,我可以成功启动我的服务,但我无法访问我的任何控制器(端口是不上市).我想我做错了什么.

After publishing it with dotnet publish and creating Windows Service with sc create I can succesfully start my service, but I can't reach any of my controllers (ports are not listeting). I assume I'm doing something wrong.

所以我想主要的问题是如何制作自托管的 web api 并将其作为 Windows 服务运行.所有找到的解决方案在 RC2 更新后都不起作用.

So I guess the main question is how to make self hosted web api and run it as Windows Service. All found solutions don't work after RC2 update.

推荐答案

这里有几个选项 - 使用 Microsoft 的 WebHostService 类、继承 WebHostService 或编写自己的.后者的原因是使用微软的实现,我们不能编写一个类型参数继承WebHostService的泛型扩展方法,因为这个类不包含无参数构造函数,也不能访问服务定位器.

You've got a couple of options here - use Microsoft's WebHostService class, inherit WebHostService or write your own. The reason for the latter being that using Microsoft's implementation, we cannot write a generic extension method with a type parameter inheriting WebHostService since this class does not contain a parameterless constructor nor can we access the service locator.

在此示例中,我将创建一个控制台应用程序,该应用程序使用 Microsoft.DotNet.Web.targets、输出 .exe 并作为 MVC 应用程序(视图、控制器等)运行.我假设创建控制台应用程序、更改 .xproj 中的目标并修改 project.json 以具有适当的发布选项以及从标准 .NET Core Web 应用程序模板复制视图、控制器和 webroot - 是微不足道的.

In this example, I'm going to create a Console Application that uses Microsoft.DotNet.Web.targets, outputs an .exe and operates as a MVC app (Views, Controllers, etc). I assume that creating the Console Application, changing the targets in the .xproj and modifying the project.json to have proper publish options and copying the Views, Controllers and webroot from the standard .NET Core web app template - is trivial.

现在是必不可少的部分:

Now the essential part:

  1. 获取这个包并确保您在 project.json 文件中的框架是 net451(或更新的)

  1. Get this package and make sure your framework in project.json file is net451 (or newer)

确保入口点中的内容根目录正确设置为应用程序 .exe 文件的发布目录,并且调用了 RunAsService() 扩展方法.例如:

Make sure the content root in the entry point is properly set to the publish directory of the application .exe file and that the RunAsService() extension method is called. E.g:

public static void Main(string[] args)
{
    var exePath= System.Diagnostics.Process.GetCurrentProcess().MainModule.FileName;
    var directoryPath = Path.GetDirectoryName(exePath);

    var host = new WebHostBuilder()
        .UseKestrel()
        .UseContentRoot(directoryPath)
        .UseStartup<Startup>()
        .Build();

    if (Debugger.IsAttached || args.Contains("--debug"))
    {
        host.Run();
    }
    else
    {
        host.RunAsService();
    }
}

现在可以使用以下命令轻松安装 .exe

The .exe can now easily be installed using the following command

    sc create MyService binPath = "FullPathToTheConsolefile.exe"

一旦服务启动,Web 应用程序就会被托管并成功找到并呈现其视图.

Once the service is started, the web application is hosted and successfully finds and renders its Views.

这种方法的一个主要好处是,这让我们可以覆盖 OnStopping、OnStarting 和 OnStarted 方法.

One major benefit of this approach is that this lets us override the OnStopping, OnStarting and OnStarted methods.

假设下面是我们自定义的继承WebHostService的类

Let's assume that the following is our custom class that inherits WebHostService

internal class CustomWebHostService : WebHostService
{
    public CustomWebHostService(IWebHost host) : base(host)
    {
    }

    protected override void OnStarting(string[] args)
    {
        // Log
        base.OnStarting(args);
    }

    protected override void OnStarted()
    {
        // More log
        base.OnStarted();
    }

    protected override void OnStopping()
    {
        // Even more log
        base.OnStopping();
    }
}

按照上述步骤,我们必须写下我们自己的扩展方法,使用我们的自定义类运行主机:

Following the steps above, we have to write down our own extension method that runs the host using our custom class:

public static class CustomWebHostWindowsServiceExtensions
{
    public static void RunAsCustomService(this IWebHost host)
    {
        var webHostService = new CustomWebHostService(host);
        ServiceBase.Run(webHostService);
    }
}

与前面的入口点示例相比,唯一需要更改的行是最后的 else 语句,它必须调用适当的扩展方法

The only line that remains to be changed from the previous example of the entry point is the else statement in the end, it has to call the proper extension method

host.RunAsCustomService();

最后,使用与上述相同的步骤安装服务.

Finally, installing the service using the same steps as above.

sc create MyService binPath = "FullPathToTheConsolefile.exe"

这篇关于将 ASP.NET Core 作为 Windows 服务托管的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆