私は.Net Core 2.0でWindowsサービスを構築しようとしていますが、丸一日頭を動かしていて、まったく進歩していません。 Microsoftのドキュメントでさえ、すべてがCore 1.0/1.1を使用しているようです。
WindowsサービスでASP.NET Coreアプリをホストする
TopShelf は2.0もサポートしていません。
すべてのコードを.Net標準クラスライブラリに入れてから.Net Frameworkアプリケーションを使用してWindowsサービスをホストする奇妙なソリューションを見てきましたが、これは私の目にはエレガントに見えず、取得しようとしています.Net Frameworkを完全に取り除きます。
現時点で私がやりたいことは可能ですか?本当に基本的なものが欠けていますか?
Windows Compatibility Pack のリリースのおかげで、サードパーティのライブラリなしでWindowsサービスを.NET Core 2.0で記述できるようになりました(執筆時点では、まだプレリリースのままです)。ページ自体が警告するように:
ただし、移植を開始する前に、移行で達成したいことを理解する必要があります。新しい.NET実装であるため、.NET Coreに移植するだけでは十分な理由にはなりません(真のファンでない限り)。
特に、.NET CoreでWindowsサービスを記述できるようになりましたが、Windows以外のプラットフォームのアセンブリはPlatformNotSupportedException
をスローするだけなので、すぐにクロスプラットフォームの互換性を得ることができません。サービスコードを使用します。これを回避することは可能ですが(たとえば、RuntimeInformation.IsOSPlatform
を使用して)、それは完全に別の質問です。
また、サードパーティのライブラリは、サービスのインストールに関してより優れたインターフェイスを提供する場合があります。執筆時点では、現在のバージョンの互換パック(2.0.0-preview1-26216-02
)はSystem.Configuration.Install
名前空間をサポートしていないため、ServiceProcessInstaller
classおよび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>
_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の答え に記載されているライブラリのいずれかを使用できます。
.NET Core 2.0 Web APIをWindowsサービスとしてホストするには。このガイドに従いました WindowsサービスでのASP.NETコアのホスト 。 Prerequisitesの部分は不明確です。いくつかの間違いの後、ここに私がやったことがあります: ソースコード
<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>
いくつかのオプションを要約します。
ServiceBase
を使用できます。もちろん、これにはターゲットマシンに.NET Frameworkをインストールする必要があります。@JeroenMostertのコメントは少し厳しいと思います。ターゲットマシンで利用可能な特定の.NET Frameworkバージョンに依存しないという魅力を見ることができます。私がリンクした2つのリポジトリはかなり人気があるので、他の多くの人も明らかに同じように感じています。
.NET Core 2.1では、HostおよびHostBuilderを使用して、サービスとして実行されるコンソールアプリケーションを取得できます。コンソールアプリケーションをコンテナ化する場合、コンテナはどこにでもデプロイでき、サービスとして実行するのとまったく同じです。 HostおよびHostBuilderを使用して、コンソールアプリでDI、ロギング、グレースフルシャットダウンなどを管理できます。見て:
.NET Core Windowsサービスを作成する簡単な方法は、Peter Kottasの DotNetCore.WindowsService library を使用することです。
NuGetパッケージはPeterKottas.DotNetCore.WindowsServiceです。 Visual Studioパッケージマネージャーコンソールを使用してインストールするには、単に実行します
Install-Package PeterKottas.DotNetCore.WindowsService
開始方法に関する注意事項 もあります。
.NET CoreアプリケーションをWindowsサービスとして実行するには、System.ServiceProcess.ServiceController NuGetパッケージが必要です。
以下は.csprojファイルです。
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>netcoreapp2.1</TargetFramework>
<RuntimeIdentifier>win7-x64</RuntimeIdentifier>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="System.ServiceProcess.ServiceController"
Version="4.5.0" />
</ItemGroup>
</Project>
Program.csファイル、
using System.ServiceProcess;
namespace WindowsService101
{
class Program
{
static void Main(string[] args)
{
using (var service = new HelloWorldService())
{
ServiceBase.Run(service);
}
}
}
}
public class HelloWorldService : ServiceBase
{
protected override void OnStart(string[] args)
{
// Code Here
}
protected override void OnStop()
{
// Code Here
}
}
ソリューションをビルドして公開します。
.exeフォルダーから管理モードでCmdプロンプトを開きますサンプル:\ WindowsService101\bin\Debug\netcoreapp2.1\publish
sc create binPath = ""
scスタート
これは完全なコップアウトかもしれませんが、Dockerのサポートが強化されているため、コンテナ内で実行されるサービスを構築できる場合があることを忘れないでください。その時点では、.netコア(2.0)のままですが、Windowsボックスで実行されます。さらに、将来どこにでも展開できます。
Dotnetコアが成熟するにつれて、サービスがホストにローカルなリソースを必要としないことを前提に、これはより優れたソリューションになります。
.NET Core 2.2
用のWindowsサービスのASP.NET Core。既存のASP.NET Coreプロジェクトに以下の変更を加えて、アプリをサービスとして実行します。
必要:PowerShell 6.2 or later
フレームワーク依存展開(FDD):
フレームワーク依存展開(FDD)は、ターゲットシステム上の.NET Coreの共有システム全体バージョンの存在に依存します。 ASP.NET Core Windows ServiceアプリでFDDシナリオを使用すると、SDKはフレームワーク依存の実行可能ファイルと呼ばれる実行可能ファイル(* .exe)を生成します。
Windows Runtime Identifier(RID) をターゲットフレームワークを含む<PropertyGroup>
に追加します。次の例では、RIDはwin7-x64
に設定されています。 <SelfContained>
プロパティセットをfalse
に追加します。これらのプロパティは、Windows用の実行可能(.exe)ファイルを生成するようSDKに指示します。
通常、ASP.NET Coreアプリの公開時に生成されるweb.configファイルは、Windowsサービスアプリには不要です。 web.configファイルの作成を無効にするには、<IsTransformWebConfigDisabled>
プロパティセットをtrue
に追加します。
<PropertyGroup>
<TargetFramework>netcoreapp2.2</TargetFramework>
<RuntimeIdentifier>win7-x64</RuntimeIdentifier>
<SelfContained>false</SelfContained>
<IsTransformWebConfigDisabled>true</IsTransformWebConfigDisabled>
</PropertyGroup>
自己完結型展開(SCD):
自己完結型展開(SCD)は、ターゲットシステム上の共有コンポーネントの存在に依存しません。ランタイムとアプリの依存関係は、アプリと共にホスティングシステムにデプロイされます。
Windowsランタイム識別子(RID) の存在を確認するか、ターゲットフレームワークを含む<PropertyGroup>
にRIDを追加します。 <IsTransformWebConfigDisabled>
プロパティセットをtrue
に追加して、web.configファイルの作成を無効にします。
<PropertyGroup>
<TargetFramework>netcoreapp2.2</TargetFramework>
<RuntimeIdentifier>win7-x64</RuntimeIdentifier>
<IsTransformWebConfigDisabled>true</IsTransformWebConfigDisabled>
</PropertyGroup>
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) =>
WebHost.CreateDefaultBuilder(args)
.ConfigureLogging((hostingContext, logging) =>
{
logging.AddEventLog();
})
.ConfigureAppConfiguration((context, config) =>
{
// Configure the app here.
})
.UseStartup<Startup>();
}
フレームワーク依存展開(FDD)を公開します。
dotnet publish --configuration Release --output c:\svc
自己完結型の展開(SCD)を公開する
RIDは、プロジェクトファイルの<RuntimeIdenfifier>
(または<RuntimeIdentifiers>
)プロパティで指定する必要があります。 dotnet publish
コマンドの -r | --runtime オプションにランタイムを指定します。
dotnet publish --configuration Release --runtime win7-x64 --output c:\svc
icacls コマンドを管理用PowerShell 6コマンドシェル経由で使用して、アプリのフォルダーへの書き込み/読み取り/実行アクセスを許可します。
icacls "{PATH}" /grant "{USER ACCOUNT}:(OI)(CI){PERMISSION FLAGS}" /t
コマンド:
icacls "c:\svc" /grant "ServiceUser:(OI)(CI)WRX" /t
RegisterService.ps1 PowerShellスクリプトを使用して、サービスを登録します。 PowerShell 6の管理コマンドシェルから、次のコマンドを使用してスクリプトを実行します。
.\RegisterService.ps1
-Name MyService
-DisplayName "My Cool Service"
-Description "This is the Sample App service."
-Exe "c:\svc\SampleApp.exe"
-User Desktop-PC\ServiceUser
Start-Service -Name {NAME}
PowerShell 6コマンドでサービスを開始します。
Start-Service -Name MyService
イベントの開始と停止の処理
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();
}
}
拡張方法:
public static class WebHostServiceExtensions
{
public static void RunAsCustomService(this IWebHost Host)
{
var webHostService = new CustomWebHostService(Host);
ServiceBase.Run(webHostService);
}
}
Program.Main:
Host.RunAsCustomService();
コンテンツルートパスをアプリのフォルダーに設定します:
Program.Main:
var pathToExe = Process.GetCurrentProcess().MainModule.FileName;
var pathToContentRoot = Path.GetDirectoryName(pathToExe);
Directory.SetCurrentDirectory(pathToContentRoot);
CreateWebHostBuilder(args)
.Build()
.RunAsService();
ソース:
https://github.com/aspnet/AspNetCore.Docs/tree/master/aspnetcore/Host-and-deploy/windows-service/
https://docs.Microsoft.com/en-us/aspnet/core/Host-and-deploy/windows-service?view=aspnetcore-2.2
MicrosoftがMicrosoft.Windows.Compatibilityをリリースしたので、将来の使用に最適であると思われるので、それを使用します。
自己インストールサービスの簡単な例はこちら https://github.com/janantos/service_core