基本は↓に書いてあるのだけど、所々間違っている?というか、バージョンアップあたりで動かなくなっているので、ポイントだけメモ書き。
Windows サービスで ASP.NET Core をホストします。
https://docs.microsoft.com/ja-jp/aspnet/core/host-and-deploy/windows-service?view=aspnetcore-2.0&tabs=aspnetcore2x
https://github.com/aspnet/Docs/tree/master/aspnetcore/host-and-deploy/windows-service/sample
*.csprojでターゲットを.NET Frameworkにする
ASP.NET Core + .NET Core で作成したプロジェクト(*.csproj)を開いて、TargetFramework を「netcoreapp2.0」から「net461」に変える。
<PropertyGroup> <TargetFramework>netcoreapp2.0</TargetFramework> </PropertyGroup>
から
<PropertyGroup> <TargetFramework>net461</TargetFramework> <RuntimeIdentifier>win7-x64</RuntimeIdentifier> </PropertyGroup>
に変更する。
これは Windows サービスを使うために .NET Framework に切り替えているので、Linux上で動かす場合は、netcoreapp2.0 で使うことになる。
NuGetパッケージを変更する
ASP.NET Core を使っているところを、.NET Core から .NET Framework のものに切り替える。あと「Microsoft.AspNetCore.Hosting.WindowsServices」を追加して、Windows サービスで起動するための RunAsService() を使えるようにしておく。
<ItemGroup> <PackageReference Include="Microsoft.AspNetCore.All" Version="2.0.8" /> </ItemGroup>
から
<ItemGroup> <PackageReference Include="Microsoft.AspNetCore" Version="2.0.3" /> <PackageReference Include="Microsoft.AspNetCore.Mvc" Version="2.0.4" /> <PackageReference Include="Microsoft.AspNetCore.Hosting.WindowsServices" Version="2.0.3" /> </ItemGroup>
Program.csを書き替える
ASP.NET Core + .NET Core の場合には、IWebHost インターフェースを使っているのだが、面倒なので、Main に書き替えてしまう。
public class Program { public static void Main(string[] args) { BuildWebHost(args).Run(); } public static IWebHost BuildWebHost(string[] args) => WebHost.CreateDefaultBuilder(args) .UseStartup<Startup>() .Build(); }
から
using Microsoft.AspNetCore; using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.Hosting.WindowsServices; public class Program { public static void Main(string[] args) { bool isService = false; if (Debugger.IsAttached || args.Contains("--console")) { isService = false; } if ( args.Contains("--service")) { isService = true; } // パラメータを消しておく args = new string[] { }; if (isService) { // サービスで動作させる var pathToExe = Process.GetCurrentProcess().MainModule.FileName; var pathToContentRoot = Path.GetDirectoryName(pathToExe); var host = WebHost.CreateDefaultBuilder(args) .UseContentRoot(pathToContentRoot) .UseStartup<Startup>() .Build(); host.RunAsService(); } else { // コンソールアプリで起動する var host = WebHost.CreateDefaultBuilder(args) .UseStartup<Startup>() .UseUrls($"http://*:{port}") .Build(); host.Run(); } } }
起動スイッチを付けて通常起動とサービスの起動に切り替えている。MSのサンプルでは、デフォルトでサービス起動になっているのだが、こちらは「–service」を付けたときだけ、Windows サービスで起動するようにしている。
WebHost.CreateDefaultBuilder に不要なパラメータを渡すと落ちるので、args の中身を消しておく(なんとなくバグ臭いのだが)。
サービスで起動する
サービスを登録するために sc コマンドを管理者権限のコマンドプロンプトで実行する。
sc create UsbService binpath="D:\work\SG\git\usbblocker\UsbBlocker.Web\bin\Debug\net461\win7-x64\UsbBlocker.Web.exe --service"
binpath には、フルパスを指定する。スイッチを付けるためにダブルクォートで囲ってある。サービス名は UsbService としているが、ダブらないように自前で名前をつける。
サービスの起動は sc start でできる。
sb start UsbBlockerService
サービスを削除するときは sc delete する。
sb delete UsbBlockerService