2017-10-04 172 views
9

我試圖在.Net Core 2.0中構建一個Windows服務,但是我一直在牆上敲打我的頭一整天並沒有任何進展。 一切似乎都可以用核1.0/1.1,即使微軟文檔:.Net Core 2.0 Windows服務

Host an ASP.NET Core app in a Windows Service

TopShelf不支持2.0爲好,因爲我已經看到了。

我見過一些奇怪的解決方案,將所有的代碼放在.Net標準類庫中,然後使用.Net框架應用程序來承載Windows服務,但這在我看來並不優雅, m試圖擺脫.Net框架。

我現在想要做甚麼?我錯過了一些非常基本的東西?

+0

[Windows服務與.NET核心]可能的重複(https://stackoverflow.com/questions/41014513/windows-service-with-net-core) –

+0

'試圖擺脫.Net框架乾脆'試圖建立一個_Windows_服務可能是一場艱苦的戰鬥.. – thisextendsthat

回答

2

僅僅因爲對基於.NET的Windows服務的支持駐留在.NET Framework中,您不能。

每引用您的文檔:

先決條件

  • 應用程序必須在.NET框架運行時運行。

一個直接的原因是,該服務使用Microsoft.AspNetCore.Hosting.WindowsServices軟件包,它依賴於.NET框架本身。

+0

你有什麼要說的這個https://github.com/dasMulli/dotnet-win32-service – DGaspar

+0

它可以在Windows 64上正常工作嗎? –

+0

@maxman當我測試它時,它與.net Core 2.0不兼容,所以我不得不使用https://github.com/PeterKottas/DotNetCore.WindowsService – DGaspar

5

我總結的一些選項:

  1. 移動你的代碼到.NET標準庫,並在.NET框架應用主機,所以你可以使用ServiceBase。這當然需要在目標機器上安裝.NET Framework
  2. 使用NSSM(非吸入服務管理器)來管理.NET Core控制檯應用程序(它具有公共域許可證)
  3. 使用Windows API調用掛鉤到Windows服務方法。這是DotNetCore.WindowsServicedotnet-win32-service(都是MIT許可)所採取的做法

我覺得@ JeroenMostert的評論是有點苛刻 - 我可以看到不依賴於特定的.NET Framework版本上是可用的吸引力目標機器。其他人顯然也有同樣的感受,因爲我所鏈接的2個回購渠道相當受歡迎。

+0

我刪除了我的評論。我還寫了一個新的答案,指出現在有一個基於MS的.NET Core 2.0服務解決方案(儘管使用一些第三方解決方案仍然更方便)。我相信這能舒緩任何刺耳的情緒。 :-) –

0

也許這是一個完整的cop-out,但請記住,如果有更多的docker支持,您可以構建一個在容器中運行的服務。在那一點上,它仍然是.net核心(2.0),但在你的Windows機器上運行。更重要的是,你可以在將來任何地方部署。

隨着dotnet核心的成熟,我認爲這是一個更好更好的解決方案,假設您的服務不需要本地主機的資源。

1

現在可以在沒有第三方庫的情況下使用.NET Core 2.0編寫Windows服務,這要歸功於Windows Compatibility Pack的發佈(在撰寫本文時,仍處於預發佈階段)。正如頁面本身警告的那樣:

但是在你開始移植之前,你應該明白你想用 完成遷移。只是移植到.NET Core,因爲它是 新的.NET實現並不是一個很好的理由(除非你是一個真正的粉絲)。

特別是,在.NET核心編寫Windows服務現在是可能的,但你不會得到跨平臺兼容性,開箱即用,因爲Windows以外平臺上的組件將只是拋出一個PlatformNotSupportedException如果您嘗試使用服務代碼。可以解決這個問題(例如使用RuntimeInformation.IsOSPlatform),但這完全是另一個問題。

另外,第三方庫在安裝服務方面仍然可以提供更好的接口:從編寫起,當前版本的兼容包(2.0.0-preview1-26216-02)不支持System.Configuration.Install命名空間,因此缺省方法ServiceProcessInstaller類和installutil將不起作用。稍後更多。我們假設您已經從項目模板中創建了一個全新的Windows服務(Service1)(由於它不包含任何有趣的內容,除了繼承自ServiceBase的類以外沒有任何其他內容),所以我們假設您已經創建了一個全新的Windows服務(Service1)。所有你需要做的,使之建立在.NET核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> 

,然後刪除properties\AssemblyInfo.cs因爲它不再需要將與版本信息發生衝突項目本身。

如果您已經有服務並且具有相關性,轉換可能會更復雜。請參閱here

現在你應該可以運行dotnet publish並獲得一個可執行文件。如上所述,您不能使用ServiceProcessInstaller類來安裝該服務,因此您必須手動輸入

  • 註冊服務使用的事件源;
  • 創建實際的服務。

這可以通過一些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) 

這不是在幾個方面的理想:這個硬編碼的消息資源文件的路徑(我們真的應該確定它在哪裏來自注冊表中的可執行文件路徑和運行時路徑),並對服務名稱和可執行文件名稱進行硬編碼。您可能希望通過在Program.cs中執行一些命令行解析來爲您的項目提供自己的安裝功能,或使用Cocowalla's answer中提到的其中一個庫。

+0

我目前有我的服務與https://github.com/dasMulli/dotnet-win32-service運行,但是當我可以嘗試和搗鼓這個解決方案,因爲它看起來像最好的未來打樣,而且它看起來會是原生的做法。如果一切順利,我會接受你的答案。 – DGaspar