.Net Core 2.0 Служба Windows

Я пытаюсь создать службу Windows в .NET Core 2.0, но я стучал головой о стену на целый день и никакого прогресса вообще. Все, кажется, использует Core 1.0/1.1 даже документацию Microsoft:

Разместить приложение ASP.NET Core в службе Windows

TopShelf также не поддерживает 2.0, для того, что я видел.

Я видел некоторые странные решения, которые поместили весь код в .Net Standard Class Library, а затем с помощью приложения .Net Framework для размещения Windows Service, но это не выглядит элегантно в моих глазах, и я пытаясь вообще избавиться от .NET Framework.

Я хочу сделать то, что я хочу сделать на данный момент? Я пропустил что-то действительно основное?

Ответ 1

Теперь можно создать службу Windows в.NET Core 2.0 без сторонних библиотек, благодаря выпуску пакета совместимости Windows (на момент написания, все еще в предварительном порядке). Поскольку сама страница предупреждает:

Но прежде чем приступить к портированию, вы должны понять, чего хотите добиться при миграции. Просто портирование на.NET Core, потому что это новая реализация.NET, не является достаточно хорошей причиной (если вы не настоящий вентилятор).

В частности, теперь возможно создание службы Windows в.NET Core, но вы не получите межплатформенную совместимость из коробки, потому что сборки для платформ, отличных от Windows, будут просто бросать исключение PlatformNotSupportedException если вы попытаетесь использовать служебный код, Работа вокруг этого возможна (например, с использованием RuntimeInformation.IsOSPlatform), но это еще один вопрос.

Кроме того, сторонние библиотеки могут по-прежнему предлагать более удобный интерфейс для установки службы: 2.0.0-preview1-26216-02 с записи, текущая версия пакета совместимости (2.0.0-preview1-26216-02) не поддерживает System.Configuration.Install пространство имен, поэтому подход по умолчанию с классом ServiceProcessInstaller и 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 поскольку он больше не требуется и будет конфликтовать с информацией о версии в самом проекте.

Если у вас уже есть служба, и у нее есть зависимости, преобразование может быть более сложным. См. Здесь.

Теперь вы сможете запустить 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.

Ответ 2

Для размещения веб-API.NET Core 2.0 в качестве службы Windows. Я следил за этим руководством Host ASP.NET Core в службе Windows. Часть предварительных требований мне непонятна. После некоторых ошибок, вот что я сделал: Исходный код

  1. Создание основного веб-приложения ASP.NET 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>

Ответ 3

Я подведу некоторые варианты:

  • Переместите свой код в библиотеку .NET Standard и разместите его в приложении .NET Framework, чтобы вы могли использовать ServiceBase. Разумеется, для установки на целевой машине .NET Framework необходимо установить
  • Используйте NSSM (диспетчер служб, не относящийся к сосанию) для управления консольным приложением .NET Core (у него есть лицензия для общедоступного домена)
  • Используйте вызовы Windows API, чтобы подключиться к методам службы Windows. Это подход, используемый DotNetCore.WindowsService и dotnet-win32-service (оба лицензированы MIT)

Я думаю, комментарий @JeroenMostert немного суровый - я вижу, что привлекательность не зависит от конкретной версии .NET Framework, доступной на целевых машинах. Многие другие, очевидно, чувствуют то же самое, что и 2 репозиции, с которыми я связан, довольно популярны.

Ответ 4

В .NET Core 2.1 вы можете использовать Host и HostBuilder для получения консольного приложения, которое работает как сервис. Если вы контейнеризуете консольное приложение, вы можете развернуть контейнер в любом месте, и это все равно, что запускать в качестве службы. Вы можете использовать Host и HostBuilder для управления DI, ведением журнала, корректным завершением работы и т.д. В консольном приложении. Посмотри на:

Услуги хостинга в консольном приложении .NET Core

Ответ 5

Простым способом создания службы.NET Core Windows является использование библиотеки DotNetCore.WindowsService от Peter Kottas.

Пакет NuGet - это PeterKottas.DotNetCore.WindowsService. Чтобы установить его с помощью консоли управления пакетами Visual Studio, просто запустите

Install-Package PeterKottas.DotNetCore.WindowsService

Есть хорошие заметки о том, как начать работу.

Ответ 6

Вы не можете, просто потому, что поддержка .NET Services на основе .NET находится в .NET Framework.

В документации, на которую вы ссылаетесь:

Предпосылки

  • Приложение должно запускаться во время выполнения платформы .NET.

Одна прямолинейная причина заключается в том, что служба использует пакет Microsoft.AspNetCore.Hosting.WindowsServices, который зависит от самой .NET Framework.

Ответ 7

Возможно, это полная копия, но помните, что с большей поддержкой докеров вы можете создать службу, которая работает в контейнере. В этот момент это все равно будет .net core (2.0), но работает на вашем окне окна. Что еще, вы могли бы развернуть практически в любом месте в будущем.

Как ядро ​​dotnet созревает, я это лучшее и лучшее решение, предполагая, что ваша служба не требует ресурсов, локальных для хоста.

Ответ 8

Нам просто нужен пакет NuGet System.ServiceProcess.ServiceController для запуска приложения .NET Core в качестве службы Windows.

Ниже приведен файл .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. Откройте Cmd Prompt в режиме администратора из папки .exe Пример:\WindowsService101\bin\Debug\netcoreapp2.1\publish

  2. sc create binPath = ""

  3. sc start

Ответ 9

ASP.NET Core в службе Windows для .NET Core 2.2. Внесите следующие изменения в существующий проект ASP.NET Core, чтобы запустить приложение как службу:

Требуется: PowerShell 6.2 or later

Развертывание, зависящее от платформы (FDD):

Внедрение, зависящее от платформы (FDD), зависит от наличия общесистемной версии .NET Core в целевой системе. Когда сценарий FDD используется с приложением ASP.NET Core Windows Service, SDK создает исполняемый файл (*.exe), который называется исполняемым файлом, зависящим от инфраструктуры.

Добавьте идентификатор времени выполнения Windows (RID) в <PropertyGroup> которая содержит целевую платформу. В следующем примере RID установлен на win7-x64. Добавьте для <SelfContained> значение false. Эти свойства инструктируют SDK генерировать исполняемый файл (.exe) для Windows.

Файл web.config, который обычно создается при публикации приложения ASP.NET Core, не требуется для приложения служб 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) или добавьте RID в <PropertyGroup> которая содержит целевую платформу. Отключите создание файла web.config, добавив для <IsTransformWebConfigDisabled> значение true.

<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>();
}

Опубликуйте Framework-зависимое развертывание (FDD):

dotnet publish --configuration Release --output c:\svc

Опубликовать автономное развертывание (SCD)

RID должен быть указан в <RuntimeIdenfifier> (или <RuntimeIdentifiers>) файла проекта. Укажите время выполнения для опции untime -r | - -r команды dotnet publish.

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) - Флаг наследования объекта распространяет права доступа к подчиненным файлам.
  • (CI) - флаг "Контейнерное наследование" распространяет разрешения на подчиненные папки.
  • {ФЛАГИ РАЗРЕШЕНИЯ} - Устанавливает права доступа к приложению.
    • Написать (W)
    • Читать (R)
    • Выполнить (X)
    • Полный (F)
    • Изменить (М)
  • /t - рекурсивно применять к существующим подчиненным папкам и файлам.

Команда:

icacls "c:\svc" /grant "ServiceUser:(OI)(CI)WRX" /t

Используйте сценарий PowerShell RegisterService.ps1 для регистрации службы. Из административной командной оболочки 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

Запустите службу с помощью команды PowerShell 6 Start-Service -Name {NAME}.

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

Ответ 10

Поскольку Microsoft выпустила Microsoft.Windows.Compatibility, я бы использовал ее, поскольку она кажется лучшей для будущего использования.

Простой пример службы самостоятельной установки находится здесь https://github.com/janantos/service_core

Ответ 11

Для тех, кто ищет этот вопрос, но хочет реализовать службу Windows с .NET Core 3.x

https://csharp.christiannagel.com/2019/10/15/windowsservice/

Комбинация общего хоста плюс фоновая служба плюс инструмент командной строки sc и у вас есть служба Windows.