.Net Core 2.0 Windows-service

Ik probeer een Windows-service te bouwen in .Net Core 2.0, maar ik loop al een hele dag met mijn hoofd tegen de muur en er komt helemaal geen vooruitgang.
Alles lijkt Core 1.0/1.1 te gebruiken, zelfs de Microsoft-documentatie:

Een ASP.NET Core-app hosten in een Windows-service

TopShelfondersteunt ook 2.0 niet, voor zover ik heb gezien.

Ik heb rare oplossingen gezien die alle code in een .Net Standard Class Library plaatsen en vervolgens een .Net Framework-toepassing gebruiken om de Windows-service te hosten, maar dit ziet er in mijn ogen niet elegant uit en ik ben proberen helemaal van.Net Framework af te komen.

Is wat ik wil doen op dit moment wel mogelijk? Mis ik iets heel basaals?


Antwoord 1, autoriteit 100%

Het is nu mogelijk om een ​​Windows-service te schrijven in .NET Core 2.0 zonder bibliotheken van derden, dankzij de release van de Windows Compatibility Pack(op het moment van schrijven, nog in pre-release). Zoals de pagina zelf waarschuwt:

Maar voordat u begint met overzetten, moet u weten wat u wilt
bereiken met de migratie. Gewoon overzetten naar .NET Core omdat het zo is
een nieuwe .NET-implementatie is geen goede reden (tenzij je een
echte fan).

Met name het schrijven van een Windows-service in .NET Core is nu misschien mogelijk, maar u krijgt geen platformonafhankelijke compatibiliteit uit de doos, omdat de assemblages voor andere platforms dan Windows gewoon een PlatformNotSupportedExceptionals u probeert de servicecode te gebruiken. Hier omheen werken is mogelijk (bijvoorbeeld met behulp van RuntimeInformation.IsOSPlatform), maar dat is een andere vraag.

Ook kunnen bibliotheken van derden nog steeds een mooiere interface bieden met betrekking tot het installeren van de service: op het moment van schrijven, de huidige versie van het compatibiliteitspakket (2.0.0-preview1-26216-02) ondersteunt de naamruimte System.Configuration.Installniet, dus de standaardbenadering met een klasse ServiceProcessInstalleren installutilzal niet werken. Daarover later meer.

Dat gezegd hebbende, laten we aannemen dat je een gloednieuwe Windows-service (Service1) hebt gemaakt op basis van de projectsjabloon (niet strikt vereist omdat het niets interessants bevat, behalve een klasse die overerft van ServiceBase). Het enige dat u hoeft te doen om het op .NET Core 2.0 te laten bouwen, is door de .csprojte bewerken en te vervangen door het nieuwe formaat:

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

En verwijder vervolgens properties\AssemblyInfo.csaangezien dit niet langer nodig is en in strijd is met versie-informatie in het project zelf.

Als u al een service heeft en deze afhankelijkheden heeft, kan de conversie ingewikkelder zijn. Zie hier.

Nu zou je in staat moeten zijn om dotnet publishuit te voeren en een uitvoerbaar bestand te krijgen. Zoals vermeld, kunt u de klasse ServiceProcessInstallerniet gebruiken om de service te installeren, dus u zult handmatig

  • registreer de gebeurtenisbron die de service gebruikt;
  • maak de eigenlijke service.

Dit kan met een bepaalde PowerShell. Vanaf een verhoogde prompt op de locatie die uw gepubliceerde uitvoerbare bestand bevat:

$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)

Dit is op verschillende manieren niet ideaal: hiermee wordt het pad van het bronbestand van het bericht hard gecodeerd (we zouden echt moeten bepalen waar het zich bevindt van het uitvoerbare bestand en de runtime-paden in het register), en het codeert de service hard naam en uitvoerbare naam. Misschien wilt u uw project zijn eigen installatiemogelijkheden geven door wat opdrachtregelparsing uit te voeren in Program.cs, of door een van de bibliotheken te gebruiken die worden vermeld in Het antwoord van Cocowalla.


Antwoord 2, autoriteit 61%

Om .NET Core 2.0 Web API te hosten als Windows-service. Ik heb deze handleiding gevolgd Host ASP. NET Core in een Windows-service. Het gedeelte Vereistenis mij onduidelijk. Na wat fouten, hier is wat ik deed:
Broncode

  1. Een ASP.NET Core-webtoepassing maken
    voer hier de afbeeldingsbeschrijving in
  2. Kies API
    voer hier de afbeeldingsbeschrijving in
  3. Bewerk .csproj-bestand, moet het doelframework wijzigen van netcoreapp2.0in net461, vermeld expliciet alle pakketverwijzingen in plaats van Microsoft.AspNetCore te gebruiken. Alle, als volgt
<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>

Snippet uitvouwen


Antwoord 3, autoriteit 46%

Ik zal enkele opties samenvatten:

  1. Verplaats uw code naar een .NET Standard-bibliotheek en host deze in een .NET Framework-app, zodat u ServiceBasekunt gebruiken. Hiervoor moet natuurlijk het .NET Framework op de doelcomputer zijn geïnstalleerd
  2. Gebruik NSSM(de Non-Sucking Service Manager) om een ​​.NET Core console-app te beheren (deze heeft een publiek domein licentie)
  3. Gebruik Windows API-aanroepen om verbinding te maken met Windows-servicemethoden. Dit is de benadering van DotNetCore.WindowsServiceen dotnet-win32-service(beide hebben een MIT-licentie)

Ik denk dat de opmerking van @JeroenMostert een beetje hard is – ik zie de aantrekkingskracht van het niet afhankelijk zijn van een bepaalde .NET Framework-versie die beschikbaar is op de doelmachines. Veel anderen voelen duidelijk hetzelfde, aangezien de 2 repo’s waarnaar ik heb gelinkt nogal populair zijn.


Antwoord 4, autoriteit 32%

In .NET Core 2.1 kunt u de Host en HostBuilder gebruiken om een ​​consoletoepassing te krijgen die als een service wordt uitgevoerd. Als u uw consoletoepassing in een container plaatst, kunt u de container overal implementeren en het is net hetzelfde als draaien als een service. U kunt de Host en HostBuilder gebruiken om DI, Logging, Graceful Shutdown, enz. in uw console-app te beheren. Kijk eens naar:

Hostingservices in .NET Core-consoletoepassing


Antwoord 5, autoriteit 14%

Een gemakkelijke manier om een ​​.NET Core Windows-service te maken is door Peter Kottas’ DotNetCore.WindowsService-bibliotheek te gebruiken .

Het NuGet-pakket is PeterKottas.DotNetCore.WindowsService. Om het te installeren met behulp van de Visual Studio Package Manager Console, voert u gewoon

Install-Package PeterKottas.DotNetCore.WindowsService

Er zijn goede opmerkingen over hoe u aan de slag kunt gaan, ook.


Antwoord 6, autoriteit 11%

We hebben alleen het System.ServiceProcess.ServiceController NuGet-pakket nodig om een ​​.NET Core-toepassing als Windows-service uit te voeren.

Hierna volgt het .csproj-bestand,

<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-bestand,

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

Bouw en publiceer de oplossing.

  1. Open Cmd Prompt in Admin mode vanuit de .exe map
    Voorbeeld: \WindowsService101\bin\Debug\netcoreapp2.1\publish

  2. sc create binPath=””

  3. sc start


Antwoord 7, autoriteit 11%

ASP.NET Core in een Windows-service voor .NET Core 2.2. Breng de volgende wijzigingen aan in een bestaand ASP.NET Core-project om de app als een service uit te voeren:

Vereist: PowerShell 6.2 or later

Kaderafhankelijke implementatie (FDD):

Framework-dependent deployment (FDD) is afhankelijk van de aanwezigheid van een gedeelde systeembrede versie van .NET Core op het doelsysteem. Wanneer het FDD-scenario wordt gebruikt met een ASP.NET Core Windows Service-app, produceert de SDK een uitvoerbaar bestand (*.exe), een framework-afhankelijk uitvoerbaar bestand genoemd.

Voeg een Windows Runtime Identifier (RID)toe aan de <PropertyGroup>die het doelframework bevat. In het volgende voorbeeld is de RID ingesteld op win7-x64. Voeg de eigenschap <SelfContained>toe die is ingesteld op false. Deze eigenschappen instrueren de SDK om een ​​uitvoerbaar (.exe) bestand voor Windows te genereren.

Een web.config-bestand, dat normaal gesproken wordt geproduceerd bij het publiceren van een ASP.NET Core-app, is niet nodig voor een Windows Services-app. Om het maken van het web.config-bestand uit te schakelen, voegt u de eigenschap <IsTransformWebConfigDisabled>toe die is ingesteld op true.

<PropertyGroup>
  <TargetFramework>netcoreapp2.2</TargetFramework>
  <RuntimeIdentifier>win7-x64</RuntimeIdentifier>
  <SelfContained>false</SelfContained>
  <IsTransformWebConfigDisabled>true</IsTransformWebConfigDisabled>
</PropertyGroup>

Zelfstandige implementatie (SCD):

Zelfstandige implementatie (SCD) is niet afhankelijk van de aanwezigheid van gedeelde componenten op het doelsysteem. De runtime en de afhankelijkheden van de app worden samen met de app geïmplementeerd op het hostingsysteem.

Bevestig de aanwezigheid van een Windows Runtime Identifier (RID)of voeg een RID toe aan de <PropertyGroup>die het doelframework bevat. Schakel het maken van een web.config-bestand uit door de eigenschap <IsTransformWebConfigDisabled>toe te voegen die is ingesteld op true.

<PropertyGroup>
  <TargetFramework>netcoreapp2.2</TargetFramework>
  <RuntimeIdentifier>win7-x64</RuntimeIdentifier>
  <IsTransformWebConfigDisabled>true</IsTransformWebConfigDisabled>
</PropertyGroup>

Programmahoofd

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

Een framework-afhankelijke implementatie (FDD) publiceren:

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

Een op zichzelf staande implementatie (SCD) publiceren

De RID moet worden opgegeven in de eigenschap <RuntimeIdenfifier>(of <RuntimeIdentifiers>) van het projectbestand. Lever de runtime aan de -r|–runtimeoptie van het dotnet publishcommando.

dotnet publish --configuration Release --runtime win7-x64 --output c:\svc

Verleen schrijf-/lees-/uitvoertoegang tot de map van de app met behulp van de icacls-opdracht via een administratieve PowerShell 6-opdrachtshell.

icacls "{PATH}" /grant "{USER ACCOUNT}:(OI)(CI){PERMISSION FLAGS}" /t
  • {PATH} – Pad naar de map van de app.
  • {USER ACCOUNT} – Het gebruikersaccount (SID).
  • (OI) – De vlag Object Inherit propageert machtigingen naar ondergeschikte
    bestanden.
  • (CI) – De container Inherit-vlag verspreidt machtigingen naar:
    onderliggende mappen.
  • {PERMISSION FLAGS} – Stelt de toegangsrechten van de app in.
    • Schrijf (W)
    • Lees (R)
    • Uitvoeren (X)
    • Vol (F)
    • Aanpassen (M)
  • /t – Recursief toepassen op bestaande onderliggende mappen en bestanden.

Opdracht:

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

Gebruik de RegisterService .ps1PowerShell-script om de service te registreren. Voer vanuit een administratieve PowerShell 6-opdrachtshell het script uit met de volgende opdracht:

.\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 de service met de Start-Service -Name {NAME}PowerShell 6-opdracht.

Start-Service -Name MyService

Gebeurtenissen starten en stoppen

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

Uitbreidingsmethode:

public static class WebHostServiceExtensions
{
    public static void RunAsCustomService(this IWebHost host)
    {
        var webHostService = new CustomWebHostService(host);
        ServiceBase.Run(webHostService);
    }
}

Program.Main:

host.RunAsCustomService();

Stel het hoofdpad van de inhoud in op de map van de app:

Program.Main:

var pathToExe = Process.GetCurrentProcess().MainModule.FileName;
var pathToContentRoot = Path.GetDirectoryName(pathToExe);
Directory.SetCurrentDirectory(pathToContentRoot);
CreateWebHostBuilder(args)
    .Build()
    .RunAsService();

Bron:

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


Antwoord 8, autoriteit 7%

Misschien is dit een complete cop-out, maar vergeet niet dat met een grotere docker-ondersteuning, kunt u mogelijk een service bouwen die loopt in een container. Op dat moment zou het nog steeds .NET-kern (2.0) zijn, maar op uw Windows-doos. Bovendien kunt u in de toekomst zo ongeveer overal inzetten.

Als DotNet Core Matures, I Dit is een betere en betere oplossing, ervan uitgaande dat uw service geen middelen nodig heeft voor de host.


9, Autoriteit 4%

Voor degenen die deze vraag vinden, maar een Windows-service willen implementeren met .NET CORE 3.X

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

Een combinatie van de generieke host plus de achtergronddienst plus de Commandline Tool SC en u hebt een Windows-service.

Other episodes