作者:Luke Latham
不使用 IIS 时,可以在 Windows 上将 ASP.NET Core 应用作为 Windows 服务进行托管。 作为 Windows 服务进行托管时,应用将在服务器重新启动后自动启动。
ASP.NET Core 辅助角色服务模板可作为编写长期服务应用的起点。 要使用该模板作为编写 Windows 服务应用的基础:
将辅助角色服务 (worker
) 模板用于命令行界面中的 dotnet new 命令。 下面的示例中创建了名为 ContosoWorker
的辅助角色服务应用。 执行命令时会自动为 ContosoWorker
应用创建文件夹。
dotnet new worker -o ContosoWorker
应用需要 Microsoft.AspNetCore.Hosting.WindowsServices 的包引用。
生成主机时会调用 IHostBuilder.UseWindowsService
。 若应用作为 Windows 服务运行,方法为:
WindowsServiceLifetime
。CreateDefaultBuilder
生成主机的应用,默认日志级别为“警告” 或更高级别。Logging:EventLog:LogLevel:Default
键覆盖默认日志级别。在 Program.cs 的 CreateHostBuilder
中 :
Host.CreateDefaultBuilder(args) .UseWindowsService() ...
本主题附带了以下示例应用:
有关 MVC 指南,请参阅 ASP.NET Core MVC 概述 和 从 ASP.NET Core 2.2 迁移到3.0 下的文章。
有关部署方案的信息和建议,请参阅 .NET Core 应用程序部署。
对于使用 Razor Pages 或 MVC 框架的基于 Web 应用的服务,请在项目文件中指定 Web SDK:
<Project Sdk="Microsoft.NET.Sdk.Web">
如果服务仅执行后台任务(例如 托管服务),请在项目文件中指定辅助角色 SDK:
<Project Sdk="Microsoft.NET.Sdk.Worker">
依赖框架的部署 (FDD) 依赖目标系统上存在共享系统级版本的 .NET Core。 按照本文中的指南采用 FDD 方案时,SDK 会生成一个称为“依赖框架的可执行文件”的可执行文件 (.exe)。
如果使用 Web SDK,则 web.config 文件(通常在发布 ASP.NET Core 应用时生成)不是 Windows 服务应用的必要文件 。 若要禁止创建 web.config 文件,请将 <IsTransformWebConfigDisabled>
属性集添加到 true
。
<PropertyGroup> <TargetFramework>netcoreapp3.0</TargetFramework> <IsTransformWebConfigDisabled>true</IsTransformWebConfigDisabled> </PropertyGroup>
独立部署 (SCD) 不依赖主机系统上存在的共享框架。 运行时和应用的依赖项将与应用一起部署。
将 Windows 运行时标识符 (RID) 添加到包含目标框架的 <PropertyGroup>
中:
<RuntimeIdentifier>win7-x64</RuntimeIdentifier>
要发布多个 RID:
有关详细信息,请参阅 .NET Core RID 目录。
在管理 PowerShell 6 命令行界面中运行 New-LocalUser cmdlet,为服务创建用户帐户。
对于 Windows 10 2018 年 10 月更新(版本 1809/内部版本 10.0.17763)或更高版本:
New-LocalUser -Name {SERVICE NAME}
对于 Windows 10 2018 年 10 月更新(版本 1809/内部版本 10.0.17763)之前的 Windows 操作系统:
powershell -Command "New-LocalUser -Name {SERVICE NAME}"
在系统提示时,提供强密码。
除非将 -AccountExpires
参数提供给到期时间为 DateTime 的 New-LocalUser cmdlet,否则用户帐户不会到期。
有关详细信息,请参阅 Microsoft.PowerShell.LocalAccounts 和服务用户帐户。
使用 Active Directory 时管理用户的另一种方法是使用托管服务帐户。 有关详细信息,请参阅组托管服务帐户概述。
为服务用户帐户创建“以服务身份登录”权限:
{DOMAIN OR COMPUTER NAME\USER}
),然后选择“确定”,以将此用户添加到策略。 使用 PowerShell 注册服务。 从 PowerShell 6 命令行界面,执行以下命令:
$acl = Get-Acl "{EXE PATH}" $aclRuleArgs = {DOMAIN OR COMPUTER NAME\USER}, "Read,Write,ReadAndExecute", "ContainerInherit,ObjectInherit", "None", "Allow" $accessRule = New-Object System.Security.AccessControl.FileSystemAccessRule($aclRuleArgs) $acl.SetAccessRule($accessRule) $acl | Set-Acl "{EXE PATH}" New-Service -Name {SERVICE NAME} -BinaryPathName {EXE FILE PATH} -Credential {DOMAIN OR COMPUTER NAME\USER} -Description "{DESCRIPTION}" -DisplayName "{DISPLAY NAME}" -StartupType Automatic
{EXE PATH}
– 应用在主机上的文件夹的路径(如 d:\myservice
)。 请勿在此路径中包含应用的可执行文件。 尾部反斜杠是非必需项。{DOMAIN OR COMPUTER NAME\USER}
– 服务用户帐户(如 Contoso\ServiceUser
)。{SERVICE NAME}
– 服务名称(如 MyService
)。{EXE FILE PATH}
– 应用的可执行文件路径(如 d:\myservice\myservice.exe
)。 请将可执行文件的文件名和扩展名包括在内。{DESCRIPTION}
– 服务说明(如 My sample service
)。{DISPLAY NAME}
– 服务显示名称(如 My Service
)。使用以下 PowerShell 6 命令启动服务:
Start-Service -Name {SERVICE NAME}
此命令需要几秒钟才能启动服务。
要检查服务的状态,请使用以下 PowerShell 6 命令:
Get-Service -Name {SERVICE NAME}
状态报告为以下值之一:
Starting
Running
Stopping
Stopped
使用以下 Powershell 6 命令停止服务:
Stop-Service -Name {SERVICE NAME}
在停止服务一小段时间后,使用以下 Powershell 6 命令删除服务:
Remove-Service -Name {SERVICE NAME}
与来自 Internet 或公司网络的请求进行交互且在代理或负载均衡器后方的服务可能需要其他配置。 有关详细信息,请参阅 配置 ASP.NET Core 以使用代理服务器和负载均衡器。
默认情况下,ASP.NET Core 绑定到 http://localhost:5000
。 通过设置 ASPNETCORE_URLS
环境变量来配置 URL 和端口。
有关其他 URL 和端口配置方法,请参阅相关服务器文章:
上述指南介绍了对 HTTPS 终结点的支持。 例如,在使用 Windows 服务进行身份验证时,为 HTTPS 配置应用。
备注
不支持使用 ASP.NET Core HTTPS 开发证书保护服务终结点。
通过为 Windows 服务调用 GetCurrentDirectory 返回的当前工作目录是 C:\WINDOWS\system32 文件夹。 system32 文件夹不是存储服务文件(如设置文件)的合适位置 。 使用以下方法之一来维护和访问服务的资产和设置文件。
使用 IHostEnvironment.ContentRootPath 或 ContentRootFileProvider 查找应用的资源。
应用作为服务运行时,UseWindowsService 将 ContentRootPath 设置为 AppContext.BaseDirectory。
通过调用 CreateDefaultBuilder during host construction,从应用的内容根加载应用的默认设置文件 appsettings.json 和 appsettings.{Environment}.json。
对于 ConfigureAppConfiguration 中的开发人员代码加载的其他设置文件,无需调用 SetBasePath。 在下面的示例中,custom_settings.json 文件位于应用的内容根,加载它时未显式设置基本路径:
public class Program { public static void Main(string[] args) { CreateHostBuilder(args).Build().Run(); } public static IHostBuilder CreateHostBuilder(string[] args) => Host.CreateDefaultBuilder(args) .UseWindowsService() .ConfigureAppConfiguration((hostingContext, config) => { config.AddJsonFile("custom_settings.json"); }) .ConfigureServices((hostContext, services) => { services.AddHostedService<Worker>(); }); }
请勿尝试使用 GetCurrentDirectory 来获取资源路径,因为 Windows 服务应用会返回“C:\WINDOWS\system32”文件夹作为其当前目录。
使用 IConfigurationBuilder 时,使用 SetBasePath 指定到包含文件的文件夹的绝对路径。
若要排除 Windows 服务应用的故障,请参阅 ASP.NET Core 项目疑难解答和调试。
New-Service
PowerShell 命令时,用户密码已过期,或以不正确的方式传递。访问系统和应用程序事件日志:
许多启动错误未在事件日志中生成有用信息。 可以通过在托管系统上在命令提示符处运行应用来找到某些错误的原因。 若要记录应用中的其他详细信息,则降低日志级别,或在开发环境中运行此应用。
正常运行的应用在开发计算机上升级 .NET Core SDK 或在应用内更改包版本后可能会立即出现故障。 在某些情况下,不同的包可能在执行主要升级时中断应用。 可以按照以下说明来修复其中大部分问题:
删除 bin 和 obj 文件夹。
通过从命令行界面执行 dotnet nuget locals all --clear 清除包缓存。
清除包缓存还可通过使用 nuget.exe 工具并执行命令 nuget locals all -clear
来完成。 nuget.exe 不是与 Windows 桌面操作系统的捆绑安装,必须从 NuGet 网站中单独获取。
还原并重新生成项目。
在重新部署应用前,在服务器上删除部署文件夹中的所有文件。
故障转储是系统内存的一个快照,可帮助确定应用崩溃、启动故障或应用速度缓慢等状况的原因 。
从 Windows 错误报告 (WER) 中获取转储并进行分析:
创建文件夹,将崩溃转储文件保存在 c:\dumps
。
使用应用程序可执行文件名称运行 EnableDumps PowerShell 脚本:
.\EnableDumps {APPLICATION EXE} c:\dumps
在造成崩溃的条件下运行应用。
出现崩溃后,运行 DisableDumps PowerShell 脚本:
.\DisableDumps {APPLICATION EXE}
在应用崩溃并完成转储收集后,即可正常终止应用。 PowerShell 脚本会 WER 来按应用收集转储(最多收集 5 个)。
警告
崩溃转储可能会占用大量磁盘空间(每个最多占用数 GB)。
如果应用挂起(停止响应但不崩溃)、在启动期间失败或者正常运行hangs,请参阅用户模式转储文件:选择最佳工具,以选择适合用于生成转储的工具。
可采用几种方法来分析转储。 有关详细信息,请参阅分析用户模式转储文件。
不使用 IIS 时,可以在 Windows 上将 ASP.NET Core 应用作为 Windows 服务进行托管。 作为 Windows 服务进行托管时,应用将在服务器重新启动后自动启动。
应用需要引用 Microsoft.AspNetCore.Hosting.WindowsServices 和 Microsoft.Extensions.Logging.EventLog 包。
在服务之外运行时,若要进行测试和调试,请添加代码以确定应用是否作为服务或控制台应用运行。 检查是否已连接调试器或是否存在 --console
开关。 如果其中一个条件为 true(应用不作为服务运行),请调用 Run。 如果条件为 false(应用作为服务运行):
CreateWebHostBuilder
中配置应用。由于命令行配置提供程序需要命令行参数的名称/值对,因此将先从参数中删除 --console
开关,然后 CreateDefaultBuilder 会接收这些参数。
若要写入 Windows 事件日志,请将事件日志提供程序添加到 ConfigureLogging。 使用 appsettings.Production.json 文件中的 Logging:LogLevel:Default
键设置日志记录级别。
示例应用中的以下示例调用了 RunAsCustomService
,来代替 RunAsService,以处理应用内的生存期事件。 有关详细信息,请参阅处理启动和停止事件部分。
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) => WebHost.CreateDefaultBuilder(args) .ConfigureLogging((hostingContext, logging) => { logging.AddEventLog(); }) .ConfigureAppConfiguration((context, config) => { // Configure the app here. }) .UseStartup<Startup>(); }
有关部署方案的信息和建议,请参阅 .NET Core 应用程序部署。
对于使用 Razor Pages 或 MVC 框架的基于 Web 应用的服务,请在项目文件中指定 Web SDK:
<Project Sdk="Microsoft.NET.Sdk.Web">
如果服务仅执行后台任务(例如 托管服务),请在项目文件中指定辅助角色 SDK:
<Project Sdk="Microsoft.NET.Sdk.Worker">
依赖框架的部署 (FDD) 依赖目标系统上存在共享系统级版本的 .NET Core。 按照本文中的指南采用 FDD 方案时,SDK 会生成一个称为“依赖框架的可执行文件”的可执行文件 (.exe)。
Windows 运行时标识符 (RID) (<RuntimeIdentifier>) 包含目标框架。 在以下示例中,将 RID 设置为 win7-x64
。 <SelfContained>
属性设置为 false
。 这些属性指示 SDK 生成用于 Windows 的可执行文件 (.exe ) 以及一个依赖共享 NET Core 框架的应用。
web.config 文件(通常在发布 ASP.NET Core 应用时生成)对于 Windows 服务应用来说是不必要的。 若要禁止创建 web.config 文件,请将 <IsTransformWebConfigDisabled>
属性集添加到 true
。
<PropertyGroup> <TargetFramework>netcoreapp2.2</TargetFramework> <RuntimeIdentifier>win7-x64</RuntimeIdentifier> <SelfContained>false</SelfContained> <IsTransformWebConfigDisabled>true</IsTransformWebConfigDisabled> </PropertyGroup>
独立部署 (SCD) 不依赖主机系统上存在的共享框架。 运行时和应用的依赖项将与应用一起部署。
将 Windows 运行时标识符 (RID) 添加到包含目标框架的 <PropertyGroup>
中:
<RuntimeIdentifier>win7-x64</RuntimeIdentifier>
要发布多个 RID:
有关详细信息,请参阅 .NET Core RID 目录。
将 <SelfContained>
属性设置为 true
:
<SelfContained>true</SelfContained>
在管理 PowerShell 6 命令行界面中运行 New-LocalUser cmdlet,为服务创建用户帐户。
对于 Windows 10 2018 年 10 月更新(版本 1809/内部版本 10.0.17763)或更高版本:
New-LocalUser -Name {SERVICE NAME}
对于 Windows 10 2018 年 10 月更新(版本 1809/内部版本 10.0.17763)之前的 Windows 操作系统:
powershell -Command "New-LocalUser -Name {SERVICE NAME}"
在系统提示时,提供强密码。
除非将 -AccountExpires
参数提供给到期时间为 DateTime 的 New-LocalUser cmdlet,否则用户帐户不会到期。
有关详细信息,请参阅 Microsoft.PowerShell.LocalAccounts 和服务用户帐户。
使用 Active Directory 时管理用户的另一种方法是使用托管服务帐户。 有关详细信息,请参阅组托管服务帐户概述。
为服务用户帐户创建“以服务身份登录”权限:
{DOMAIN OR COMPUTER NAME\USER}
),然后选择“确定”,以将此用户添加到策略。 使用 PowerShell 注册服务。 从 PowerShell 6 命令行界面,执行以下命令:
$acl = Get-Acl "{EXE PATH}" $aclRuleArgs = {DOMAIN OR COMPUTER NAME\USER}, "Read,Write,ReadAndExecute", "ContainerInherit,ObjectInherit", "None", "Allow" $accessRule = New-Object System.Security.AccessControl.FileSystemAccessRule($aclRuleArgs) $acl.SetAccessRule($accessRule) $acl | Set-Acl "{EXE PATH}" New-Service -Name {SERVICE NAME} -BinaryPathName {EXE FILE PATH} -Credential {DOMAIN OR COMPUTER NAME\USER} -Description "{DESCRIPTION}" -DisplayName "{DISPLAY NAME}" -StartupType Automatic
{EXE PATH}
– 应用在主机上的文件夹的路径(如 d:\myservice
)。 请勿在此路径中包含应用的可执行文件。 尾部反斜杠是非必需项。{DOMAIN OR COMPUTER NAME\USER}
– 服务用户帐户(如 Contoso\ServiceUser
)。{SERVICE NAME}
– 服务名称(如 MyService
)。{EXE FILE PATH}
– 应用的可执行文件路径(如 d:\myservice\myservice.exe
)。 请将可执行文件的文件名和扩展名包括在内。{DESCRIPTION}
– 服务说明(如 My sample service
)。{DISPLAY NAME}
– 服务显示名称(如 My Service
)。使用以下 PowerShell 6 命令启动服务:
Start-Service -Name {SERVICE NAME}
此命令需要几秒钟才能启动服务。
要检查服务的状态,请使用以下 PowerShell 6 命令:
Get-Service -Name {SERVICE NAME}
状态报告为以下值之一:
Starting
Running
Stopping
Stopped
使用以下 Powershell 6 命令停止服务:
Stop-Service -Name {SERVICE NAME}
在停止服务一小段时间后,使用以下 Powershell 6 命令删除服务:
Remove-Service -Name {SERVICE NAME}
处理 OnStarting、OnStarted 和 OnStopping 事件:
使用 OnStarting
、OnStarted
和 OnStopping
方法创建从 WebHostService 派生的类:
[DesignerCategory("Code")] 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.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(); } }
创建可将 CustomWebHostService
传递给 Run 的 IWebHost 的扩展方法:
public static class WebHostServiceExtensions { public static void RunAsCustomService(this IWebHost host) { var webHostService = new CustomWebHostService(host); ServiceBase.Run(webHostService); } }
在 Program.Main
中,调用 RunAsCustomService
扩展方法,而不是 RunAsService:
host.RunAsCustomService();
若要在 Program.Main
中查看 RunAsService 的位置,请参阅部署类型部分中所示的代码示例。
与来自 Internet 或公司网络的请求进行交互且在代理或负载均衡器后方的服务可能需要其他配置。 有关详细信息,请参阅 配置 ASP.NET Core 以使用代理服务器和负载均衡器。
默认情况下,ASP.NET Core 绑定到 http://localhost:5000
。 通过设置 ASPNETCORE_URLS
环境变量来配置 URL 和端口。
有关其他 URL 和端口配置方法,请参阅相关服务器文章:
上述指南介绍了对 HTTPS 终结点的支持。 例如,在使用 Windows 服务进行身份验证时,为 HTTPS 配置应用。
备注
不支持使用 ASP.NET Core HTTPS 开发证书保护服务终结点。
通过为 Windows 服务调用 GetCurrentDirectory 返回的当前工作目录是 C:\WINDOWS\system32 文件夹。 system32 文件夹不是存储服务文件(如设置文件)的合适位置 。 使用以下方法之一来维护和访问服务的资产和设置文件。
ContentRootPath 是创建服务时提供给 binPath
参数的同一路径。 请调用包含应用内容根目录的路径的 SetCurrentDirectory,而不是调用 GetCurrentDirectory
来创建设置文件的路径。
在 Program.Main
中,确定服务可执行文件的文件夹路径,并使用该路径来建立应用的内容根:
var pathToExe = Process.GetCurrentProcess().MainModule.FileName; var pathToContentRoot = Path.GetDirectoryName(pathToExe); Directory.SetCurrentDirectory(pathToContentRoot); CreateWebHostBuilder(args) .Build() .RunAsService();
使用 IConfigurationBuilder 时,使用 SetBasePath 指定到包含文件的文件夹的绝对路径。
若要排除 Windows 服务应用的故障,请参阅 ASP.NET Core 项目疑难解答和调试。
New-Service
PowerShell 命令时,用户密码已过期,或以不正确的方式传递。访问系统和应用程序事件日志:
许多启动错误未在事件日志中生成有用信息。 可以通过在托管系统上在命令提示符处运行应用来找到某些错误的原因。 若要记录应用中的其他详细信息,则降低日志级别,或在开发环境中运行此应用。
正常运行的应用在开发计算机上升级 .NET Core SDK 或在应用内更改包版本后可能会立即出现故障。 在某些情况下,不同的包可能在执行主要升级时中断应用。 可以按照以下说明来修复其中大部分问题:
删除 bin 和 obj 文件夹。
通过从命令行界面执行 dotnet nuget locals all --clear 清除包缓存。
清除包缓存还可通过使用 nuget.exe 工具并执行命令 nuget locals all -clear
来完成。 nuget.exe 不是与 Windows 桌面操作系统的捆绑安装,必须从 NuGet 网站中单独获取。
还原并重新生成项目。
在重新部署应用前,在服务器上删除部署文件夹中的所有文件。
故障转储是系统内存的一个快照,可帮助确定应用崩溃、启动故障或应用速度缓慢等状况的原因 。
从 Windows 错误报告 (WER) 中获取转储并进行分析:
创建文件夹,将崩溃转储文件保存在 c:\dumps
。
使用应用程序可执行文件名称运行 EnableDumps PowerShell 脚本:
.\EnableDumps {APPLICATION EXE} c:\dumps
在造成崩溃的条件下运行应用。
出现崩溃后,运行 DisableDumps PowerShell 脚本:
.\DisableDumps {APPLICATION EXE}
在应用崩溃并完成转储收集后,即可正常终止应用。 PowerShell 脚本会 WER 来按应用收集转储(最多收集 5 个)。
警告
崩溃转储可能会占用大量磁盘空间(每个最多占用数 GB)。
如果应用挂起(停止响应但不崩溃)、在启动期间失败或者正常运行hangs,请参阅用户模式转储文件:选择最佳工具,以选择适合用于生成转储的工具。
可采用几种方法来分析转储。 有关详细信息,请参阅分析用户模式转储文件。
不使用 IIS 时,可以在 Windows 上将 ASP.NET Core 应用作为 Windows 服务进行托管。 作为 Windows 服务进行托管时,应用将在服务器重新启动后自动启动。
应用需要引用 Microsoft.AspNetCore.Hosting.WindowsServices 和 Microsoft.Extensions.Logging.EventLog 包。
在服务之外运行时,若要进行测试和调试,请添加代码以确定应用是否作为服务或控制台应用运行。 检查是否已连接调试器或是否存在 --console
开关。 如果其中一个条件为 true(应用不作为服务运行),请调用 Run。 如果条件为 false(应用作为服务运行):
CreateWebHostBuilder
中配置应用。由于命令行配置提供程序需要命令行参数的名称/值对,因此将先从参数中删除 --console
开关,然后 CreateDefaultBuilder 会接收这些参数。
若要写入 Windows 事件日志,请将事件日志提供程序添加到 ConfigureLogging。 使用 appsettings.Production.json 文件中的 Logging:LogLevel:Default
键设置日志记录级别。
示例应用中的以下示例调用了 RunAsCustomService
,来代替 RunAsService,以处理应用内的生存期事件。 有关详细信息,请参阅处理启动和停止事件部分。
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) => WebHost.CreateDefaultBuilder(args) .ConfigureLogging((hostingContext, logging) => { logging.AddEventLog(); }) .ConfigureAppConfiguration((context, config) => { // Configure the app here. }) .UseStartup<Startup>(); }
有关部署方案的信息和建议,请参阅 .NET Core 应用程序部署。
对于使用 Razor Pages 或 MVC 框架的基于 Web 应用的服务,请在项目文件中指定 Web SDK:
<Project Sdk="Microsoft.NET.Sdk.Web">
如果服务仅执行后台任务(例如 托管服务),请在项目文件中指定辅助角色 SDK:
<Project Sdk="Microsoft.NET.Sdk.Worker">
依赖框架的部署 (FDD) 依赖目标系统上存在共享系统级版本的 .NET Core。 按照本文中的指南采用 FDD 方案时,SDK 会生成一个称为“依赖框架的可执行文件”的可执行文件 (.exe)。
Windows 运行时标识符 (RID) (<RuntimeIdentifier>) 包含目标框架。 在以下示例中,将 RID 设置为 win7-x64
。 <SelfContained>
属性设置为 false
。 这些属性指示 SDK 生成用于 Windows 的可执行文件 (.exe ) 以及一个依赖共享 NET Core 框架的应用。
<UseAppHost>
属性设置为 true
。 此属性为服务提供 FDD 的激活路径(一个可执行文件,格式为 .exe )。
web.config 文件(通常在发布 ASP.NET Core 应用时生成)对于 Windows 服务应用来说是不必要的。 若要禁止创建 web.config 文件,请将 <IsTransformWebConfigDisabled>
属性集添加到 true
。
<PropertyGroup> <TargetFramework>netcoreapp2.2</TargetFramework> <RuntimeIdentifier>win7-x64</RuntimeIdentifier> <UseAppHost>true</UseAppHost> <SelfContained>false</SelfContained> <IsTransformWebConfigDisabled>true</IsTransformWebConfigDisabled> </PropertyGroup>
独立部署 (SCD) 不依赖主机系统上存在的共享框架。 运行时和应用的依赖项将与应用一起部署。
将 Windows 运行时标识符 (RID) 添加到包含目标框架的 <PropertyGroup>
中:
<RuntimeIdentifier>win7-x64</RuntimeIdentifier>
要发布多个 RID:
有关详细信息,请参阅 .NET Core RID 目录。
将 <SelfContained>
属性设置为 true
:
<SelfContained>true</SelfContained>
在管理 PowerShell 6 命令行界面中运行 New-LocalUser cmdlet,为服务创建用户帐户。
对于 Windows 10 2018 年 10 月更新(版本 1809/内部版本 10.0.17763)或更高版本:
New-LocalUser -Name {SERVICE NAME}
对于 Windows 10 2018 年 10 月更新(版本 1809/内部版本 10.0.17763)之前的 Windows 操作系统:
powershell -Command "New-LocalUser -Name {SERVICE NAME}"
在系统提示时,提供强密码。
除非将 -AccountExpires
参数提供给到期时间为 DateTime 的 New-LocalUser cmdlet,否则用户帐户不会到期。
有关详细信息,请参阅 Microsoft.PowerShell.LocalAccounts 和服务用户帐户。
使用 Active Directory 时管理用户的另一种方法是使用托管服务帐户。 有关详细信息,请参阅组托管服务帐户概述。
为服务用户帐户创建“以服务身份登录”权限:
{DOMAIN OR COMPUTER NAME\USER}
),然后选择“确定”,以将此用户添加到策略。 使用 PowerShell 注册服务。 从 PowerShell 6 命令行界面,执行以下命令:
$acl = Get-Acl "{EXE PATH}" $aclRuleArgs = {DOMAIN OR COMPUTER NAME\USER}, "Read,Write,ReadAndExecute", "ContainerInherit,ObjectInherit", "None", "Allow" $accessRule = New-Object System.Security.AccessControl.FileSystemAccessRule($aclRuleArgs) $acl.SetAccessRule($accessRule) $acl | Set-Acl "{EXE PATH}" New-Service -Name {SERVICE NAME} -BinaryPathName {EXE FILE PATH} -Credential {DOMAIN OR COMPUTER NAME\USER} -Description "{DESCRIPTION}" -DisplayName "{DISPLAY NAME}" -StartupType Automatic
{EXE PATH}
– 应用在主机上的文件夹的路径(如 d:\myservice
)。 请勿在此路径中包含应用的可执行文件。 尾部反斜杠是非必需项。{DOMAIN OR COMPUTER NAME\USER}
– 服务用户帐户(如 Contoso\ServiceUser
)。{SERVICE NAME}
– 服务名称(如 MyService
)。{EXE FILE PATH}
– 应用的可执行文件路径(如 d:\myservice\myservice.exe
)。 请将可执行文件的文件名和扩展名包括在内。{DESCRIPTION}
– 服务说明(如 My sample service
)。{DISPLAY NAME}
– 服务显示名称(如 My Service
)。使用以下 PowerShell 6 命令启动服务:
Start-Service -Name {SERVICE NAME}
此命令需要几秒钟才能启动服务。
要检查服务的状态,请使用以下 PowerShell 6 命令:
Get-Service -Name {SERVICE NAME}
状态报告为以下值之一:
Starting
Running
Stopping
Stopped
使用以下 Powershell 6 命令停止服务:
Stop-Service -Name {SERVICE NAME}
在停止服务一小段时间后,使用以下 Powershell 6 命令删除服务:
Remove-Service -Name {SERVICE NAME}
处理 OnStarting、OnStarted 和 OnStopping 事件:
使用 OnStarting
、OnStarted
和 OnStopping
方法创建从 WebHostService 派生的类:
[DesignerCategory("Code")] 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.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(); } }
创建可将 CustomWebHostService
传递给 Run 的 IWebHost 的扩展方法:
public static class WebHostServiceExtensions { public static void RunAsCustomService(this IWebHost host) { var webHostService = new CustomWebHostService(host); ServiceBase.Run(webHostService); } }
在 Program.Main
中,调用 RunAsCustomService
扩展方法,而不是 RunAsService:
host.RunAsCustomService();
若要在 Program.Main
中查看 RunAsService 的位置,请参阅部署类型部分中所示的代码示例。
与来自 Internet 或公司网络的请求进行交互且在代理或负载均衡器后方的服务可能需要其他配置。 有关详细信息,请参阅 配置 ASP.NET Core 以使用代理服务器和负载均衡器。
默认情况下,ASP.NET Core 绑定到 http://localhost:5000
。 通过设置 ASPNETCORE_URLS
环境变量来配置 URL 和端口。
有关其他 URL 和端口配置方法,请参阅相关服务器文章:
上述指南介绍了对 HTTPS 终结点的支持。 例如,在使用 Windows 服务进行身份验证时,为 HTTPS 配置应用。
备注
不支持使用 ASP.NET Core HTTPS 开发证书保护服务终结点。
通过为 Windows 服务调用 GetCurrentDirectory 返回的当前工作目录是 C:\WINDOWS\system32 文件夹。 system32 文件夹不是存储服务文件(如设置文件)的合适位置 。 使用以下方法之一来维护和访问服务的资产和设置文件。
ContentRootPath 是创建服务时提供给 binPath
参数的同一路径。 请调用包含应用内容根目录的路径的 SetCurrentDirectory,而不是调用 GetCurrentDirectory
来创建设置文件的路径。
在 Program.Main
中,确定服务可执行文件的文件夹路径,并使用该路径来建立应用的内容根:
var pathToExe = Process.GetCurrentProcess().MainModule.FileName; var pathToContentRoot = Path.GetDirectoryName(pathToExe); Directory.SetCurrentDirectory(pathToContentRoot); CreateWebHostBuilder(args) .Build() .RunAsService();
使用 IConfigurationBuilder 时,使用 SetBasePath 指定到包含文件的文件夹的绝对路径。
若要排除 Windows 服务应用的故障,请参阅 ASP.NET Core 项目疑难解答和调试。
New-Service
PowerShell 命令时,用户密码已过期,或以不正确的方式传递。访问系统和应用程序事件日志:
许多启动错误未在事件日志中生成有用信息。 可以通过在托管系统上在命令提示符处运行应用来找到某些错误的原因。 若要记录应用中的其他详细信息,则降低日志级别,或在开发环境中运行此应用。
正常运行的应用在开发计算机上升级 .NET Core SDK 或在应用内更改包版本后可能会立即出现故障。 在某些情况下,不同的包可能在执行主要升级时中断应用。 可以按照以下说明来修复其中大部分问题:
删除 bin 和 obj 文件夹。
通过从命令行界面执行 dotnet nuget locals all --clear 清除包缓存。
清除包缓存还可通过使用 nuget.exe 工具并执行命令 nuget locals all -clear
来完成。 nuget.exe 不是与 Windows 桌面操作系统的捆绑安装,必须从 NuGet 网站中单独获取。
还原并重新生成项目。
在重新部署应用前,在服务器上删除部署文件夹中的所有文件。
故障转储是系统内存的一个快照,可帮助确定应用崩溃、启动故障或应用速度缓慢等状况的原因 。
从 Windows 错误报告 (WER) 中获取转储并进行分析:
创建文件夹,将崩溃转储文件保存在 c:\dumps
。
使用应用程序可执行文件名称运行 EnableDumps PowerShell 脚本:
.\EnableDumps {APPLICATION EXE} c:\dumps
在造成崩溃的条件下运行应用。
出现崩溃后,运行 DisableDumps PowerShell 脚本:
.\DisableDumps {APPLICATION EXE}
在应用崩溃并完成转储收集后,即可正常终止应用。 PowerShell 脚本会 WER 来按应用收集转储(最多收集 5 个)。
警告
崩溃转储可能会占用大量磁盘空间(每个最多占用数 GB)。
如果应用挂起(停止响应但不崩溃)、在启动期间失败或者正常运行hangs,请参阅用户模式转储文件:选择最佳工具,以选择适合用于生成转储的工具。
可采用几种方法来分析转储。 有关详细信息,请参阅分析用户模式转储文件。