我正在尝试在.Net Core 2.0中构建Windows服务,但我已经花了一整天的时间在墙上,一点进展也没有。一切似乎都在使用Core 1.0/1.1,甚至Microsoft文档:
在Windows服务中托管ASP.NET核心应用
据我所知,TopShelf也不支持2.0。
我见过一些奇怪的解决方案,将所有代码放在.Net标准类库中,然后使用.Net Framework应用程序来托管Windows服务,但这在我看来并不优雅,我试图完全摆脱 of.Net 框架。
我现在想做的事情可能吗?我真的错过了一些基本的东西吗?
我将总结一些选项:
服务库
。这当然需要在目标计算机上安装 .NET 框架我认为@JeroenMostert的评论有点苛刻——我可以看到不依赖某个特定事物的吸引力。目标计算机上可用的. NET Framework版本。很多人显然有同样的感觉,因为我链接的两个回购非常受欢迎。
去主持。NET Core 2.0 Web API作为Windows服务。我按照这个指南主持人ASP.NET核心在一个窗口服务。先决条件部分我不清楚。在一些错误之后,这里是我所做的:源代码
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>net461</TargetFramework>
<RuntimeIdentifier>win7-x64</RuntimeIdentifier>
<!--<TargetFramework>netcoreapp2.0</TargetFramework>-->
</PropertyGroup>
<ItemGroup>
<Folder Include="wwwroot\" />
</ItemGroup>
<ItemGroup>
<!--<PackageReference Include="Microsoft.AspNetCore.All" Version="2.0.6" />-->
<PackageReference Include="Microsoft.AspNetCore" Version="2.0.2" />
<PackageReference Include="Microsoft.AspNetCore.Hosting.WindowsServices" Version="2.0.2" />
<PackageReference Include="Microsoft.AspNetCore.Mvc" Version="2.0.3" />
<PackageReference Include="Microsoft.AspNetCore.StaticFiles" Version="2.0.2" />
<PackageReference Include="Microsoft.Extensions.Logging.Debug" Version="2.0.1" />
<PackageReference Include="Microsoft.VisualStudio.Web.BrowserLink" Version="2.0.2" />
</ItemGroup>
<ItemGroup>
<DotNetCliToolReference Include="Microsoft.VisualStudio.Web.CodeGeneration.Tools" Version="2.0.3" />
</ItemGroup>
</Project>
现在可以在. NET Core 2.0中编写Windows服务而无需第三方库,这要归功于Windows兼容性包的发布(在撰写本文时,仍处于预发布阶段)。正如页面本身警告的那样:
但是在开始移植之前,您应该了解您想通过迁移完成什么。只是移植到. NET Core,因为它是一个新的。NET实现不是一个足够好的理由(除非你是真正的粉丝)。
特别是,在. NET Core中编写Windows服务现在可能是可能的,但您不会开箱即用地获得跨平台兼容性,因为如果您尝试使用服务代码,Windows以外平台的程序集只会抛出PlatformNotSupport dException
。解决这个问题是可能的(例如,使用RuntimeInformation.IsOSPlatform
),但这完全是另一个问题。
此外,第三方库可能仍然会提供关于安装服务的更好的界面:在撰写本文时,兼容包的当前版本(< code > 2 . 0 . 0-preview 1-26216-02 )不支持< code >系统。Configuration.Install命名空间,因此使用< code > ServiceProcessInstaller 类和< code>installutil的默认方法将不起作用。稍后会详细介绍。
综上所述,让我们假设您已经从项目模板创建了一个全新的Windows服务(Service1
)(不是严格要求的,因为它不包含任何有趣的东西,除了从ServiceBase
继承的类)。您需要做的就是使其构建在. NET Core 2.0是编辑并将. csproj
替换为新格式:
<Project Sdk="Microsoft.NET.Sdk" ToolsVersion="15.0">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>netcoreapp20</TargetFramework>
<RuntimeIdentifier>win-x64</RuntimeIdentifier>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Windows.Compatibility" Version="2.0.0-*" />
</ItemGroup>
</Project>
然后删除属性\AssemblyInfo.cs
因为它不再需要,并且将与项目本身中的版本信息冲突。
如果您已经有一个服务并且它具有依赖项,则转换可能会更复杂。请参阅此处。
现在,您应该能够运行 dotnet 发布
并获取可执行文件。如前所述,不能使用服务进程安装程序
类来安装服务,因此必须手动
这可以通过一些PowerShell实现。从包含已发布可执行文件的位置的提升提示:
$messageResourceFile = "C:\Windows\Microsoft.NET\Framework64\v4.0.30319\EventLogMessages.dll"
New-EventLog -LogName Application -Source Service1 -MessageResourceFile $messageResourceFile
sc.exe create Service1 binPath= (Resolve-Path .\WindowsService1.exe)
这在几个方面并不理想:这硬编码了消息资源文件的路径(我们实际上应该根据注册表中的可执行文件和运行时路径来确定它的位置),并且它硬编码了服务名和可执行文件名。您可能希望通过在< code>Program.cs中进行一些命令行解析,或者使用Cocowalla的回答中提到的一个库,为您的项目提供自己的安装功能。