如何在.NET CORE 下开发 "windows 服
2019-04-28 本文已影响33人
Nondeterminacy
原文链接:https://blog.zhuliang.ltd/back-end/build-windowsservice-netcore/
在.NET Core中并没有像 .NET Framework下的 "windows服务"可创建,但我们依然可以通过powershell这个工具,将.NET CORE 下创建的项目以"windows服务"的形式来寄宿运行。
0.新建项目
image新建、使用一个 web 应用程序 项目即可
本次示例所用.NET CORE 版本为 2.1
项目结构如下:
image1.修改项目csproj,增加RuntimeIdentifiers和IsTransformWebConfigDisabled
<PropertyGroup>
<TargetFramework>netcoreapp2.1</TargetFramework>
<RuntimeIdentifiers>win10-x64;win81-x64</RuntimeIdentifiers>
<IsTransformWebConfigDisabled>true</IsTransformWebConfigDisabled>
</PropertyGroup>
- 将Windows运行时标识符(RID)添加到包含目标框架的<PropertyGroup>。
- 如果要发布到多个Rids,则 <RuntimeIdentifier>需要用复数: <RuntimeIdentifiers>,并且不同Rid之间用分号分割,如:
<RuntimeIdentifiers>win10-x64;win81-x64</RuntimeIdentifiers>
2.添加包引用:
Microsoft.AspNetCore.Hosting.WindowsServices
Microsoft.Extensions.Logging.EventLog -------为了启用windows事件日志
启用 windows日志 start
创建一个自定义类,继承自 WebHostService ,用来重写onstarting等事件
public class MqWebHostService : WebHostService
{
private ILogger _logger;
public MqWebHostService(IWebHost host) : base(host)
{
_logger = host.Services
.GetRequiredService<ILogger<MqWebHostService>>();
}
protected override void OnStarting(string[] args)
{
_logger.LogInformation("OnStarting method called.");
base.OnStarting(args);
}
protected override void OnStarted()
{
_logger.LogInformation("OnStarted method called.");
base.OnStarted();
}
protected override void OnStopping()
{
_logger.LogInformation("OnStopping method called.");
base.OnStopping();
}
}
创建一个IHost的扩展方法,用来运行自定义的服务:MqWebHostService
public static class WebHostServiceExtensions
{
public static void RunAsCustomService(this IWebHost host)
{
var webHostService = new MqWebHostService(host);
ServiceBase.Run(webHostService);
}
}
3.修改Program.Main方法:
public class Program
{
public static void Main(string[] args)
{
var isService = !(Debugger.IsAttached || args.Contains("--console"));
if (isService)
{
var pathToExe = Process.GetCurrentProcess().MainModule.FileName;
var pathToContentRoot = Path.GetDirectoryName(pathToExe);
Directory.SetCurrentDirectory(pathToContentRoot);
}
var builder = CreateWebHostBuilder(
args.Where(arg => arg != "--console").ToArray());
var host = builder.Build();
if (isService)
{
// To run the app without the CustomWebHostService change the
// next line to host.RunAsService();
host.RunAsCustomService();
}
else
{
host.Run();
}
}
public static IWebHostBuilder CreateWebHostBuilder(string[] args)
{
var hostingConfig = new ConfigurationBuilder()
.SetBasePath(Directory.GetCurrentDirectory())
.AddJsonFile("hostsettings.json", optional: true)
.Build(); //指定 urls 键值即可,需要注意不能用IIS EXPRESS,另外对于端口而言需要避免一些不安全端口,如6000端口
return WebHost.CreateDefaultBuilder(args)
.ConfigureLogging((hostingContext, logging) =>
{
logging.SetMinimumLevel(LogLevel.Trace);
logging.AddFilter("System", LogLevel.Warning);
logging.AddFilter("Microsoft", LogLevel.Warning);
if (Environment.OSVersion.Platform == PlatformID.Unix)
{
logging.AddLog4Net("log4net.linux.config");
}
else
{
logging.AddLog4Net();
}
})
.ConfigureAppConfiguration((context, config) =>
{
// Configure the app here.
})
.UseConfiguration(hostingConfig)
.UseStartup<Startup>()
;
}
}
4.发布
- SCD部署
使用 dotnet public -c release 进行
- FDD部署
dotnet public -c release -r win81-x64
7.使用 powershell注册windows服务:
需要6.1.3 或以上版本,下载:https://github.com/PowerShell/PowerShell/releases
以下使用 localservice 这个系统服务作为用户名进行注册服务。
New-Service -Name "MqConsumerForMemberCenter" -BinaryPathName "D:\Services\MemberCenterMqConsumer\SanbenTech.MC.Mq.Subscriber.exe" -Description "会员中心消息队列 Consumer,定位用户使用小程序时的区域" -DisplayName "MqConsumerForMemberCenter" -StartupType Automatic
删除服务:
remove-service -Name "MqConsumerForMemberCenter"
也可以做成一个批处理,如下:
registerService.ps1
#Requires -Version 6.1.3
#Requires -RunAsAdministrator
param(
[Parameter(mandatory=$true)]
$Name,
[Parameter(mandatory=$true)]
$DisplayName,
[Parameter(mandatory=$true)]
$Description,
[Parameter(mandatory=$true)]
$Path,
[Parameter(mandatory=$true)]
$Exe,
[Parameter(mandatory=$true)]
$User
)
$cred = Get-Credential -Credential $User
$acl = Get-Acl $Path
$aclRuleArgs = $cred.UserName, "Read,Write,ReadAndExecute", "ContainerInherit, ObjectInherit", "None", "Allow"
$accessRule = New-Object System.Security.AccessControl.FileSystemAccessRule $aclRuleArgs
$acl.SetAccessRule($accessRule)
$acl | Set-Acl $Path
New-Service -Name $Name -BinaryPathName "$Path\$Exe" -Credential $cred -Description $Description -DisplayName $DisplayName -StartupType Automatic
如果需要用其他用户来管理服务,则可以:
1.新建用户
#创建用户
net user {mcRabbitMqSubscriber} {mypwd} /add /expires:never
#添加到组
net localgroup {GROUP} {USER ACCOUNT} /add
#删除用户
net user {user account} /delete
2.给用户赋予权限:作为服务登录
icacls "{PATH}" /grant "{USER ACCOUNT}:(OI)(CI){PERMISSION FLAGS}" /t
# {PATH} – Path to the app's folder.
# {USER ACCOUNT} – The user account (SID).
# (OI) – Object Inherit标志将权限传播给从属文件。
# (CI) – Container Inherit标志将权限传播到下级文件夹。
# {PERMISSION FLAGS} – Sets the app's access permissions.
# Write (W)
# Read (R)
# Execute (X)
# Full (F)
# Modify (M)
# /t – 递归应用于现有的从属文件夹和文件。
#如:(注意这里把useraccount OI,CI,PERMISSION FLAGS 用双引号括起来,否则报错)
icacls "X:\publish" /grant “mcRabbitMqSubscriber:(OI)(CI)WRX” /t
3.调整注册服务
registerService.ps1
#Requires -Version 6.1.3
#Requires -RunAsAdministrator
param(
[Parameter(mandatory=$true)]
$Name,
[Parameter(mandatory=$true)]
$DisplayName,
[Parameter(mandatory=$true)]
$Description,
[Parameter(mandatory=$true)]
$Path,
[Parameter(mandatory=$true)]
$Exe,
[Parameter(mandatory=$true)]
$User
)
$cred = Get-Credential -Credential $User
$acl = Get-Acl $Path
$aclRuleArgs = $cred.UserName, "Read,Write,ReadAndExecute", "ContainerInherit, ObjectInherit", "None", "Allow"
$accessRule = New-Object System.Security.AccessControl.FileSystemAccessRule $aclRuleArgs
$acl.SetAccessRule($accessRule)
$acl | Set-Acl $Path
New-Service -Name $Name -BinaryPathName "$Path\$Exe" -Credential $cred -Description $Description -DisplayName $DisplayName -StartupType Automatic
参考:
https://docs.microsoft.com/en-us/aspnet/core/host-and-deploy/windows-service?view=aspnetcore-2.1