web-dev-qa-db-ja.com

.Net Core 2.0 Windowsサービス

私は.Net Core 2.0でWindowsサービスを構築しようとしていますが、丸一日頭を動かしていて、まったく進歩していません。 Microsoftのドキュメントでさえ、すべてがCore 1.0/1.1を使用しているようです。

WindowsサービスでASP.NET Coreアプリをホストする

TopShelf は2.0もサポートしていません。

すべてのコードを.Net標準クラスライブラリに入れてから.Net Frameworkアプリケーションを使用してWindowsサービスをホストする奇妙なソリューションを見てきましたが、これは私の目にはエレガントに見えず、取得しようとしています.Net Frameworkを完全に取り除きます。

現時点で私がやりたいことは可能ですか?本当に基本的なものが欠けていますか?

46
DGaspar

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の答え に記載されているライブラリのいずれかを使用できます。

26
Jeroen Mostert

.NET Core 2.0 Web APIをWindowsサービスとしてホストするには。このガイドに従いました WindowsサービスでのASP.NETコアのホストPrerequisitesの部分は不明確です。いくつかの間違いの後、ここに私がやったことがあります: ソースコード

  1. ASP.NET Core Webアプリケーションを作成します enter image description here
  2. APIを選択 enter image description here
  3. .csprojファイルを編集し、ターゲットフレームワークをnetcoreapp2.0からnet461に変更する必要があります。 Microsoft.AspNetCore.All、次のように
<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>
  1. 電源シェル[ソリューションフォルダー] dotnet publish -o "[publish-folder]"
  2. power Shell [solution-folder] sc.exe create CoreApi binpath = "[publish-folder]\CoreApiHostedAsWindowsService.exe"
  3. 電源シェル[ソリューションフォルダー] sc.exe start CoreApi
  4. デフォルトのapi power Shellにアクセス[solution-folder] Invoke-WebRequest http:// localhost:5000/api/values
14
Chenger

いくつかのオプションを要約します。

  1. コードを.NET Standardライブラリに移動し、.NET Frameworkアプリでホストするので、ServiceBaseを使用できます。もちろん、これにはターゲットマシンに.NET Frameworkをインストールする必要があります。
  2. NSSM (Non-Sucking Service Manager)を使用して、.NET Coreコンソールアプリを管理します(パブリックドメインライセンスがあります)
  3. Windows API呼び出しを使用して、Windowsサービスメソッドにフックします。これは、 DotNetCore.WindowsService および dotnet-win32-service (両方ともMITライセンス)

@JeroenMostertのコメントは少し厳しいと思います。ターゲットマシンで利用可能な特定の.NET Frameworkバージョンに依存しないという魅力を見ることができます。私がリンクした2つのリポジトリはかなり人気があるので、他の多くの人も明らかに同じように感じています。

12
Cocowalla

.NET Core 2.1では、HostおよびHostBuilderを使用して、サービスとして実行されるコンソールアプリケーションを取得できます。コンソールアプリケーションをコンテナ化する場合、コンテナはどこにでもデプロイでき、サービスとして実行するのとまったく同じです。 HostおよびHostBuilderを使用して、コンソールアプリでDI、ロギング、グレースフルシャットダウンなどを管理できます。見て:

。NET Coreコンソールアプリケーションでのホスティングサービス

8
Peter

.NET Core Windowsサービスを作成する簡単な方法は、Peter Kottasの DotNetCore.WindowsService library を使用することです。

NuGetパッケージはPeterKottas.DotNetCore.WindowsServiceです。 Visual Studioパッケージマネージャーコンソールを使用してインストールするには、単に実行します

Install-Package PeterKottas.DotNetCore.WindowsService

開始方法に関する注意事項 もあります。

4
Josh Withee

.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
    }
}

ソリューションをビルドして公開します。

  1. .exeフォルダーから管理モードでCmdプロンプトを開きますサンプル:\ WindowsService101\bin\Debug\netcoreapp2.1\publish

  2. sc create binPath = ""

  3. scスタート

2
DeviZ

これは完全なコップアウトかもしれませんが、Dockerのサポートが強化されているため、コンテナ内で実行されるサービスを構築できる場合があることを忘れないでください。その時点では、.netコア(2.0)のままですが、Windowsボックスで実行されます。さらに、将来どこにでも展開できます。

Dotnetコアが成熟するにつれて、サービスがホストにローカルなリソースを必要としないことを前提に、これはより優れたソリューションになります。

2
Killnine

.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
  • {PATH} –アプリのフォルダーへのパス。
  • {USER ACCOUNT} –ユーザーアカウント(SID)。
  • (OI)– Object Inheritフラグは、権限を下位ファイルに伝達します。
  • (CI)– Container Inheritフラグは、権限を下位フォルダーに伝達します。
  • {PERMISSION FLAGS} –アプリのアクセス許可を設定します。
    • 書き込み(W)
    • 読み取り(R)
    • 実行(X)
    • フル(F)
    • 変更(M)
  • / 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

2
Ogglas

MicrosoftがMicrosoft.Windows.Compatibilityをリリースしたので、将来の使用に最適であると思われるので、それを使用します。

自己インストールサービスの簡単な例はこちら https://github.com/janantos/service_core

0
Jan Antoš