原文鏈接:https://blog.zhuliang.ltd/2019/04/backend/build-windowsservice-netcore.html
在.NET Core中并沒有像 .NET Framework下的 "windows服務"可創(chuàng)建,但我們依然可以通過powershell這個工具,將.NET CORE 下創(chuàng)建的項目以"windows服務"的形式來寄宿運行褂傀。
0.新建項目
新建柒室、使用一個 web 應用程序 項目即可
本次示例所用.NET CORE 版本為 2.1
項目結構如下:
1.修改項目csproj,增加RuntimeIdentifiers和IsTransformWebConfigDisabled
<PropertyGroup>
<TargetFramework>netcoreapp2.1</TargetFramework>
<RuntimeIdentifiers>win10-x64;win81-x64</RuntimeIdentifiers>
<IsTransformWebConfigDisabled>true</IsTransformWebConfigDisabled>
</PropertyGroup>
- 將Windows運行時標識符(RID)添加到包含目標框架的<PropertyGroup>蛉抓。
- 如果要發(fā)布到多個Rids庆尘,則 <RuntimeIdentifier>需要用復數(shù): <RuntimeIdentifiers>,并且不同Rid之間用分號分割巷送,如:
<RuntimeIdentifiers>win10-x64;win81-x64</RuntimeIdentifiers>
2.添加包引用:
Microsoft.AspNetCore.Hosting.WindowsServices
Microsoft.Extensions.Logging.EventLog -------為了啟用windows事件日志
啟用 windows日志 start
創(chuàng)建一個自定義類驶忌,繼承自 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();
}
}
創(chuàng)建一個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.發(fā)布
- 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 這個系統(tǒng)服務作為用戶名進行注冊服務。
New-Service -Name "MqConsumerForMemberCenter" -BinaryPathName "D:\Services\MemberCenterMqConsumer\SanbenTech.MC.Mq.Subscriber.exe" -Description "會員中心消息隊列 Consumer晤柄,定位用戶使用小程序時的區(qū)域" -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.新建用戶
#創(chuàng)建用戶
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 – 遞歸應用于現(xiàn)有的從屬文件夾和文件赚抡。
#如:(注意這里把useraccount OI,CI纠屋,PERMISSION FLAGS 用雙引號括起來涂臣,否則報錯)
icacls "X:\publish" /grant “mcRabbitMqSubscriber:(OI)(CI)WRX” /t
3.調(diào)整注冊服務
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