Mar*_*a P 31 c# windows-services .net-core asp.net-core
当我在RC2中获得它时,支持在Windows服务中托管应用程序.我试图在一个简单的web api项目上测试它(使用.NET Framework 4.6.1).
这是我的Program.cs代码:
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() {}
}
}
Run Code Online (Sandbox Code Playgroud)
所有其他的东西基本上都来自.NET Core模板(虽然我将框架更改为net461并在project.json中添加了一些依赖项).
使用dotnet publish并创建Windows服务后,sc create我可以成功启动我的服务,但是我无法访问任何控制器(端口没有监听).我想我做错了什么.
所以我想主要的问题是如何制作自托管的web api并将其作为Windows服务运行.RC2更新后,所有找到的解决方案都不起作用.
Iva*_*nov 52
你在这里有几个选择 - 使用Microsoft的WebHostService类,继承WebHostService或编写自己的.后者的原因是使用Microsoft的实现,我们不能使用继承WebHostService的类型参数编写泛型扩展方法,因为此类不包含无参数构造函数,也无法访问服务定位器.
在这个例子中,我将创建一个使用Microsoft.DotNet.Web.targets的控制台应用程序,输出.exe并作为MVC应用程序(视图,控制器等)运行.我假设创建控制台应用程序,更改.xproj中的目标并修改project.json以获得正确的发布选项并从标准.NET Core Web应用程序模板复制视图,控制器和webroot是微不足道的.
现在必不可少的部分:
获取此包并确保project.json文件中的框架是net451(或更新版本)
确保入口点中的内容根目录已正确设置为应用程序.exe文件的发布目录,并且调用了RunAsService()扩展方法.例如:
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();
}
}
Run Code Online (Sandbox Code Playgroud)现在可以使用以下命令轻松安装.exe
sc create MyService binPath = "Full\Path\To\The\Console\file.exe"
Run Code Online (Sandbox Code Playgroud)
启动服务后,将托管Web应用程序并成功查找并呈现其视图.
这种方法的一个主要好处是,它允许我们覆盖OnStopping,OnStarting和OnStarted方法.
我们假设以下是继承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();
}
}
Run Code Online (Sandbox Code Playgroud)
按照上面的步骤,我们必须写下我们自己的扩展方法,使用我们的自定义类运行主机:
public static class CustomWebHostWindowsServiceExtensions
{
public static void RunAsCustomService(this IWebHost host)
{
var webHostService = new CustomWebHostService(host);
ServiceBase.Run(webHostService);
}
}
Run Code Online (Sandbox Code Playgroud)
从前一个入口点示例中唯一要改变的行是最后的else语句,它必须调用正确的扩展方法
host.RunAsCustomService();
Run Code Online (Sandbox Code Playgroud)
最后,使用与上面相同的步骤安装服务.
sc create MyService binPath = "Full\Path\To\The\Console\file.exe"
Run Code Online (Sandbox Code Playgroud)
如果可以仅在完整的.NET Framework上运行,那么之前的答案就足够了(继承ServiceBase或使用Microsoft WebHostService).
但是,如果你想/只想在.NET Core上运行(例如在windows nano服务器上,单个二进制文件在linux上作为普通应用程序和windows上的服务工作,或者需要与应用程序并行运行旧的.NET Framework版本,因此您无法更新系统框架),您必须通过P/Invokes自己进行适当的Windows API调用.因为我必须这样做,所以我创建了一个完全正确的库.
有一个可用的示例,当使用管理权限(例如dotnet MyService.dll --register-as-service)运行时,它也能够自行安装.
您需要在Startup类中引用Microsoft.AspNetCore.Hosting和Microsoft.AspNetCore.Hosting.WindowsServices使用此代码,以使其可作为Windows服务运行:
public static void Main(string[] args)
{
var host = new WebHostBuilder()
.UseIISIntegration()
.UseKestrel()
.UseContentRoot(@"Path\To\Content\Root")
.UseStartup<Startup>()
.Build();
if (Debugger.IsAttached || args.Contains("--debug"))
{
host.Run();
}
else
{
host.RunAsService();
}
}
Run Code Online (Sandbox Code Playgroud)
然后,您需要添加一个扩展方法,IWebHost.RunAsService以WebHostService使用OnStopping和OnStarting事件处理程序将其与您的自定义类包装在一起:
public static class MyWebHostServiceServiceExtensions
{
public static void RunAsMyService(this IWebHost host)
{
var webHostService = new MyWebHostService(host);
ServiceBase.Run(webHostService);
}
}
internal class MyWebHostService : WebHostService
{
public MyWebHostService(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();
}
}
Run Code Online (Sandbox Code Playgroud)
这篇文章“ 如何在Windows服务中托管ASP.NET Core”和注释涵盖了详细信息。
UPDATE(请参阅ASP.NET Core 2.0新增功能快速摘要中的更多详细信息):
在ASP.NET Core 1.1我们有这样的事情:
public class Program
{
public static void Main(string[] args)
{
var host = new WebHostBuilder()
.UseKestrel()
.UseContentRoot(Directory.GetCurrentDirectory())
.UseIISIntegration()
.UseStartup<Startup>()
.Build();
host.Run();
}
}
Run Code Online (Sandbox Code Playgroud)
在中ASP.NET Core 2.0,它看起来像这样:
public class Program
{
public static void Main(string[] args)
{
BuildWebHost(args).Run();
}
public static IWebHost BuildWebHost(string[] args) =>
WebHost.CreateDefaultBuilder(args)
.UseStartup<Startup>()
.Build();
}
Run Code Online (Sandbox Code Playgroud)
使用最新的 VS2015 Update 2 ASP.NET Core Web 应用程序 (.NET Framework) 模板和 Program.cs 的 mods,如下所示,它在作为服务、独立运行和在 VS 中运行时运行良好。请注意,作为服务运行时需要设置包含 wwwroot 的目录的路径。
到目前为止,我真的很喜欢这个模板和模式。可以像往常一样在 Visual Studio 中开发 MVC6 代码,然后将其干净地部署为服务。事实上,我注意到,在部署服务的本地实例进行测试时,不需要使用 sc.exe 删除/创建服务。只需停止服务,发布代码并重新启动服务,它就会接受新的更改。
public class Program
{
public static void Main(string[] args)
{
IWebHost host = new WebHostBuilder()
.UseKestrel()
.UseContentRoot(Directory.GetCurrentDirectory())
.UseIISIntegration()
.UseStartup<Startup>()
.Build();
if (args.Contains("--windows-service"))
{
host = new WebHostBuilder()
.UseKestrel()
.UseContentRoot("<directory-containing-wwwroot>")
.UseIISIntegration()
.UseStartup<Startup>()
.UseUrls("http://+:5000")
.Build();
Startup.is_service = true;
host.RunAsService();
}
else
{
host.Run();
}
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
49204 次 |
| 最近记录: |