Freigeben über


Erstellen eines Windows-Diensts mit BackgroundService

.NET Framework-Entwickler sind wahrscheinlich mit Windows-Dienst-Apps vertraut. Vor .NET Core und .NET 5+ konnten Entwickler, die sich auf .NET Framework verlassen haben, Windows-Dienste erstellen, um Hintergrundaufgaben oder Prozesse mit langer Ausführungslaufzeit auszuführen. Diese Funktionalität ist weiterhin verfügbar, und Sie können Workerdienste erstellen, die als Windows-Dienst ausgeführt werden.

In diesem Tutorial lernen Sie Folgendes:

  • Veröffentlichen einer .NET-Worker-App als einzelne ausführbare Datei.
  • Erstellen eines Windows-Diensts.
  • Erstellen der BackgroundService-App als Windows-Dienst.
  • Starten und Beenden des Windows-Diensts.
  • Anzeigen von Ereignisprotokollen.
  • Löschen des Windows-Diensts.

Tipp

Der gesamte Quellcode des Beispiels „Worker in .NET“ steht im Beispielbrowser zum Download zur Verfügung. Weitere Informationen finden Sie unter Durchsuchen von Codebeispielen: Worker in .NET.

Wichtig

Bei der Installation des .NET SDK werden auch Microsoft.NET.Sdk.Worker und die Workervorlage installiert. Anders ausgedrückt: Nach der Installation des .NET SDK können Sie mithilfe des Befehls dotnet new worker einen neuen Worker erstellen. Wenn Sie Visual Studio verwenden, wird die Vorlage ausgeblendet, bis die optionale ASP.NET- und Webentwicklungsworkload installiert ist.

Voraussetzungen

Erstellen eines neuen Projekts

Um ein neues Workerdienstprojekt mit Visual Studio zu erstellen, wählen Sie Datei>Neu>Projekt... aus. Suchen Sie im Dialogfeld Neues Projekt erstellen nach „Workerdienst“, und wählen Sie die Workerdienstvorlage aus. Wenn Sie lieber die .NET-CLI verwenden möchten, öffnen Sie Ihr bevorzugtes Terminal in einem Arbeitsverzeichnis. Führen Sie den Befehl dotnet new aus, und ersetzen Sie <Project.Name> durch den gewünschten Projektnamen.

dotnet new worker --name <Project.Name>

Weitere Informationen zum .NET-CLI-Befehl für ein neues Workerdienstprojekt finden Sie unter dotnet new worker.

Tipp

Wenn Sie Visual Studio Code verwenden, können Sie .NET CLI-Befehle über das integrierte Terminal ausführen. Weitere Informationen finden Sie unter Visual Studio Code: Integriertes Terminal.

NuGet-Paket installieren

Um von .NET-IHostedService-Implementierungen aus mit nativen Windows-Diensten zu interagieren, müssen Sie das Microsoft.Extensions.Hosting.WindowsServicesNuGet-Paket installieren.

Um dies über Visual Studio zu installieren, verwenden Sie das Dialogfeld NuGet-Pakete verwalten... . Suchen Sie nach „Microsoft.Extensions.Hosting.WindowsServices“, und installieren Sie sie. Wenn Sie stattdessen die .NET-CLI verwenden, führen Sie den Befehl dotnet add package aus:

dotnet add package Microsoft.Extensions.Hosting.WindowsServices

Weitere Informationen zum .NET-CLI-Befehl zum Hinzufügen von Paketen finden Sie unter dotnet add package.

Nach dem erfolgreichen Hinzufügen der Pakete sollte Ihre Projektdatei nun die folgenden Paketverweise enthalten:

<ItemGroup>
  <PackageReference Include="Microsoft.Extensions.Hosting" Version="8.0.0" />
  <PackageReference Include="Microsoft.Extensions.Hosting.WindowsServices" Version="8.0.0" />
</ItemGroup>

Aktualisieren der Projektdatei

Dieses Workerprojekt verwendet die C#-Verweistypen, die NULL-Werte zulassen. Um sie für das gesamte Projekt zu aktivieren, aktualisieren Sie die Projektdatei entsprechend:

<Project Sdk="Microsoft.NET.Sdk.Worker">

  <PropertyGroup>
    <TargetFramework>net8.0-windows</TargetFramework>
    <Nullable>enable</Nullable>
    <ImplicitUsings>true</ImplicitUsings>
    <RootNamespace>App.WindowsService</RootNamespace>
  </PropertyGroup>

  <ItemGroup>
    <PackageReference Include="Microsoft.Extensions.Hosting" Version="8.0.0" />
    <PackageReference Include="Microsoft.Extensions.Hosting.WindowsServices" Version="8.0.0" />
  </ItemGroup>
</Project>

Die vorherigen Änderungen an der Projektdatei fügen den Knoten <Nullable>enable<Nullable> hinzu. Weitere Informationen finden Sie unter Nullwerte zulassende Verweistypen.

Erstellen des Diensts

Fügen Sie dem Projekt eine neue Klasse mit dem Namen JokeService.cs hinzu, und ersetzen Sie deren Inhalt durch den folgenden C#-Code:

namespace App.WindowsService;

public sealed class JokeService
{
    public string GetJoke()
    {
        Joke joke = _jokes.ElementAt(
            Random.Shared.Next(_jokes.Count));

        return $"{joke.Setup}{Environment.NewLine}{joke.Punchline}";
    }

    // Programming jokes borrowed from:
    // https://github.com/eklavyadev/karljoke/blob/main/source/jokes.json
    private readonly HashSet<Joke> _jokes = new()
    {
        new Joke("What's the best thing about a Boolean?", "Even if you're wrong, you're only off by a bit."),
        new Joke("What's the object-oriented way to become wealthy?", "Inheritance"),
        new Joke("Why did the programmer quit their job?", "Because they didn't get arrays."),
        new Joke("Why do programmers always mix up Halloween and Christmas?", "Because Oct 31 == Dec 25"),
        new Joke("How many programmers does it take to change a lightbulb?", "None that's a hardware problem"),
        new Joke("If you put a million monkeys at a million keyboards, one of them will eventually write a Java program", "the rest of them will write Perl"),
        new Joke("['hip', 'hip']", "(hip hip array)"),
        new Joke("To understand what recursion is...", "You must first understand what recursion is"),
        new Joke("There are 10 types of people in this world...", "Those who understand binary and those who don't"),
        new Joke("Which song would an exception sing?", "Can't catch me - Avicii"),
        new Joke("Why do Java programmers wear glasses?", "Because they don't C#"),
        new Joke("How do you check if a webpage is HTML5?", "Try it out on Internet Explorer"),
        new Joke("A user interface is like a joke.", "If you have to explain it then it is not that good."),
        new Joke("I was gonna tell you a joke about UDP...", "...but you might not get it."),
        new Joke("The punchline often arrives before the set-up.", "Do you know the problem with UDP jokes?"),
        new Joke("Why do C# and Java developers keep breaking their keyboards?", "Because they use a strongly typed language."),
        new Joke("Knock-knock.", "A race condition. Who is there?"),
        new Joke("What's the best part about TCP jokes?", "I get to keep telling them until you get them."),
        new Joke("A programmer puts two glasses on their bedside table before going to sleep.", "A full one, in case they gets thirsty, and an empty one, in case they don’t."),
        new Joke("There are 10 kinds of people in this world.", "Those who understand binary, those who don't, and those who weren't expecting a base 3 joke."),
        new Joke("What did the router say to the doctor?", "It hurts when IP."),
        new Joke("An IPv6 packet is walking out of the house.", "He goes nowhere."),
        new Joke("3 SQL statements walk into a NoSQL bar. Soon, they walk out", "They couldn't find a table.")
    };
}

readonly record struct Joke(string Setup, string Punchline);

Der vorangehende Scherzdienst-Quellcode macht eine einzelne Funktionalität verfügbar, die GetJoke-Methode. Dies ist eine string-Rückgabemethode, die einen zufälligen Programmierscherz darstellt. Das auf die Klasse bezogene Feld _jokes wird verwendet, um die Liste der Scherze zu speichern. Ein zufälliger Scherz wird aus der Liste ausgewählt und zurückgegeben.

Umschreiben der Worker-Klasse

Ersetzen Sie den vorhandenen Worker aus der Vorlage durch den folgenden C#-Code, und benennen Sie die Datei in WindowsBackgroundService.cs um:

namespace App.WindowsService;

public sealed class WindowsBackgroundService(
    JokeService jokeService,
    ILogger<WindowsBackgroundService> logger) : BackgroundService
{
    protected override async Task ExecuteAsync(CancellationToken stoppingToken)
    {
        try
        {
            while (!stoppingToken.IsCancellationRequested)
            {
                string joke = jokeService.GetJoke();
                logger.LogWarning("{Joke}", joke);

                await Task.Delay(TimeSpan.FromMinutes(1), stoppingToken);
            }
        }
        catch (OperationCanceledException)
        {
            // When the stopping token is canceled, for example, a call made from services.msc,
            // we shouldn't exit with a non-zero exit code. In other words, this is expected...
        }
        catch (Exception ex)
        {
            logger.LogError(ex, "{Message}", ex.Message);

            // Terminates this process and returns an exit code to the operating system.
            // This is required to avoid the 'BackgroundServiceExceptionBehavior', which
            // performs one of two scenarios:
            // 1. When set to "Ignore": will do nothing at all, errors cause zombie services.
            // 2. When set to "StopHost": will cleanly stop the host, and log errors.
            //
            // In order for the Windows Service Management system to leverage configured
            // recovery options, we need to terminate the process with a non-zero exit code.
            Environment.Exit(1);
        }
    }
}

Im vorangehenden Code wird JokeService zusammen mit einem ILogger eingefügt. Beide werden der Klasse als private readonly-Felder zur Verfügung gestellt. In der ExecuteAsync-Methode fordert der Scherzdienst einen Scherz an und schreibt ihn in die Protokollierung. In diesem Fall wird die Protokollierung vom Windows-Ereignisprotokoll implementiert: Microsoft.Extensions.Logging.EventLog.EventLogLogger. Protokolle werden in die Ereignisanzeige geschrieben und können dort angezeigt werden.

Hinweis

Standardmäßig lautet der Schweregrad des EreignisprotokollsWarning. Dies kann konfiguriert werden, aber zu Demonstrationszwecken protokolliert der WindowsBackgroundService mit der LogWarning-Erweiterungsmethode. Um speziell auf die EventLog-Ebene abzuzielen, fügen Sie einen Eintrag in der appsettings.{Environment}.json hinzu, oder geben Sie einen EventLogSettings.Filter-Wert an.

{
  "Logging": {
    "LogLevel": {
      "Default": "Warning"
    },
    "EventLog": {
      "SourceName": "The Joke Service",
      "LogName": "Application",
      "LogLevel": {
        "Microsoft": "Information",
        "Microsoft.Hosting.Lifetime": "Information"
      }
    }
  }
}

Weitere Informationen zum Konfigurieren von Protokollebenen finden Sie unter Protokollierungsanbieter in .NET: Windows-EventLog.

Umschreiben der Program-Klasse

Ersetzen Sie den Inhalt der Vorlagendatei Program.cs durch den folgenden C#-Code:

using App.WindowsService;
using Microsoft.Extensions.Logging.Configuration;
using Microsoft.Extensions.Logging.EventLog;

HostApplicationBuilder builder = Host.CreateApplicationBuilder(args);
builder.Services.AddWindowsService(options =>
{
    options.ServiceName = ".NET Joke Service";
});

LoggerProviderOptions.RegisterProviderOptions<
    EventLogSettings, EventLogLoggerProvider>(builder.Services);

builder.Services.AddSingleton<JokeService>();
builder.Services.AddHostedService<WindowsBackgroundService>();

IHost host = builder.Build();
host.Run();

Die AddWindowsService-Erweiterungsmethode konfiguriert die App so, dass sie als Windows-Dienst funktioniert. Der Dienstname ist auf ".NET Joke Service" festgelegt. Der gehostete Dienst ist für die Abhängigkeitsinjektion registriert.

Weitere Informationen zum Registrieren von Diensten finden Sie unter Abhängigkeitsinjektion in .NET.

Veröffentlichen der App

Um die .NET-Workerdienst-App als Windows-Dienst zu erstellen, wird empfohlen, die App als einzelne ausführbare Datei zu veröffentlichen. Eine eigenständige ausführbare Datei ist weniger fehleranfällig, da sich keine abhängigen Dateien im Dateisystem befinden. Sie können jedoch eine andere Veröffentlichungsmethode wählen. Das ist absolut akzeptabel, solange Sie eine *.exe-Datei erstellen, die vom Windows-Dienststeuerungs-Manager als Ziel verwendet werden kann.

Wichtig

Ein alternativer Veröffentlichungsansatz besteht im Erstellen der *.dll (anstelle einer *.exe-Datei), und wenn Sie die veröffentlichte App mit dem Windows-Dienststeuerungs-Manager installieren, delegieren Sie an die .NET-CLI und übergeben die DLL. Weitere Informationen finden Sie unter .NET-CLI: dotnet-Befehl.

sc.exe create ".NET Joke Service" binpath="C:\Path\To\dotnet.exe C:\Path\To\App.WindowsService.dll"
<Project Sdk="Microsoft.NET.Sdk.Worker">

  <PropertyGroup>
    <TargetFramework>net8.0-windows</TargetFramework>
    <Nullable>enable</Nullable>
    <ImplicitUsings>true</ImplicitUsings>
    <RootNamespace>App.WindowsService</RootNamespace>
    <OutputType>exe</OutputType>
    <PublishSingleFile Condition="'$(Configuration)' == 'Release'">true</PublishSingleFile>
    <RuntimeIdentifier>win-x64</RuntimeIdentifier>
    <PlatformTarget>x64</PlatformTarget>
  </PropertyGroup>

  <ItemGroup>
    <PackageReference Include="Microsoft.Extensions.Hosting" Version="8.0.0" />
    <PackageReference Include="Microsoft.Extensions.Hosting.WindowsServices" Version="8.0.0" />
  </ItemGroup>
</Project>

Die oben hervorgehobenen Zeilen der Projektdatei definieren die folgenden Verhaltensweisen:

  • <OutputType>exe</OutputType>: Erstellt eine Konsolenanwendung.
  • <PublishSingleFile Condition="'$(Configuration)' == 'Release'">true</PublishSingleFile>: aktiviert die Veröffentlichung von Einzeldateien.
  • <RuntimeIdentifier>win-x64</RuntimeIdentifier>: Gibt die RID von win-x64 an.
  • <PlatformTarget>x64</PlatformTarget>: Gibt die 64-Bit-Zielplattform-CPU an.

Um die App aus Visual Studio zu veröffentlichen, können Sie ein Veröffentlichungsprofil erstellen, das persistent gespeichert wird. Das Veröffentlichungsprofil basiert auf XML und weist die Dateierweiterung .pubxml auf. Visual Studio verwendet dieses Profil zur impliziten Veröffentlichung der App, während Sie bei Verwendung der .NET CLI explizit angeben müssen, dass das Veröffentlichungsprofil verwendet werden soll.

Klicken Sie im Projektmappen-Explorer mit der rechten Maustaste auf das Projekt, und wählen Sie Veröffentlichen... aus. Wählen Sie dann Veröffentlichungsprofil hinzufügen aus, um ein Profil zu erstellen. Wählen Sie im Dialogfeld Veröffentlichen die Option Ordner als Ziel aus.

The Visual Studio Publish dialog

Behalten Sie den standardmäßigen Speicherort bei, und wählen Sie dann Fertig stellen aus. Sobald das Profil erstellt ist, wählen Sie Alle Einstellungen anzeigen aus, und überprüfen Sie Ihre Profileinstellungen.

The Visual Studio Profile settings

Stellen Sie sicher, dass die folgenden Einstellungen angegeben sind:

  • Bereitstellungsmodus: Eigenständig
  • Einzelne Datei erstellen: markiert
  • ReadyToRun-Kompilierung aktivieren: markiert
  • Nicht verwendete Assemblys kürzen (Vorschau) : nicht geprüft

Wählen Sie abschließend Veröffentlichen aus. Die App wird kompiliert und die resultierende EXE-Datei im /publish-Ausgabeverzeichnis veröffentlicht.

Alternativ könnten Sie die .NET-CLI verwenden, um die App zu veröffentlichen:

dotnet publish --output "C:\custom\publish\directory"

Weitere Informationen finden Sie unter dotnet publish.

Wichtig

Wenn Sie mit .NET 6 versuchen, die App mit der Einstellung <PublishSingleFile>true</PublishSingleFile> zu debuggen, ist dies nicht möglich. Weitere Informationen finden Sie unter Anfügen an CoreCLR beim Debuggen einer .NET 6-App mit PublishSingleFile nicht möglich.

Erstellen des Windows-Diensts

Wenn Sie mit der Verwendung von PowerShell nicht vertraut sind und lieber ein Installationsprogramm für Ihren Dienst erstellen möchten, lesen Sie Erstellen eines Windows-Dienst-Installationsprogramms. Verwenden Sie andernfalls zum Erstellen des Windows-Diensts den Erstellungsbefehl (sc.exe) des nativen Dienststeuerungs-Managers von Windows. Führen Sie PowerShell als Administrator aus.

sc.exe create ".NET Joke Service" binpath="C:\Path\To\App.WindowsService.exe"

Tipp

Wenn Sie den Inhaltsstamm der Hostkonfiguration ändern müssen, können Sie ihn als Befehlszeilenargument übergeben, wenn Sie binpath angeben:

sc.exe create "Svc Name" binpath="C:\Path\To\App.exe --contentRoot C:\Other\Path"

Sie sehen eine Ausgabemeldung:

[SC] CreateService SUCCESS

Weitere Informationen finden Sie unter sc.exe create.

Konfigurieren des Windows-Diensts

Nachdem der Dienst erstellt wurde, können Sie ihn optional konfigurieren. Wenn Sie mit den Standardeinstellungen des Diensts einverstanden sind, fahren Sie mit dem Abschnitt Überprüfen der Dienstfunktionalität weiter.

Windows-Dienste stellen Wiederherstellungskonfigurationsoptionen zur Verfügung. Sie können die aktuelle Konfiguration mithilfe des Befehls sc.exe qfailure "<Service Name>" (wobei <Service Name> der Name Ihrer Dienste ist) abfragen, um die aktuellen Wiederherstellungskonfigurationswerte zu lesen:

sc qfailure ".NET Joke Service"
[SC] QueryServiceConfig2 SUCCESS

SERVICE_NAME: .NET Joke Service
        RESET_PERIOD (in seconds)    : 0
        REBOOT_MESSAGE               :
        COMMAND_LINE                 :

Der Befehl gibt die Wiederherstellungskonfiguration aus. Dabei handelt es sich um die Standardwerte, da diese noch nicht konfiguriert wurden.

The Windows Service recovery configuration properties dialog.

Verwenden Sie zum Konfigurieren der Wiederherstellung sc.exe failure "<Service Name>", wobei <Service Name> der Name Ihres Diensts ist:

sc.exe failure ".NET Joke Service" reset=0 actions=restart/60000/restart/60000/run/1000
[SC] ChangeServiceConfig2 SUCCESS

Tipp

Zum Konfigurieren der Wiederherstellungsoptionen muss Ihre Terminalsitzung als Administrator ausgeführt werden.

Nachdem sie erfolgreich konfiguriert wurde, können Sie die Werte mit dem Befehl sc.exe qfailure "<Service Name>" erneut abfragen:

sc qfailure ".NET Joke Service"
[SC] QueryServiceConfig2 SUCCESS

SERVICE_NAME: .NET Joke Service
        RESET_PERIOD (in seconds)    : 0
        REBOOT_MESSAGE               :
        COMMAND_LINE                 :
        FAILURE_ACTIONS              : RESTART -- Delay = 60000 milliseconds.
                                       RESTART -- Delay = 60000 milliseconds.
                                       RUN PROCESS -- Delay = 1000 milliseconds.

Die konfigurierten Neustartwerte werden angezeigt.

The Windows Service recovery configuration properties dialog with restart enabled.

Dienstwiederherstellungsoptionen und .NET-BackgroundService-Instanzen

Mit .NET 6 wurden .NET neue Verhalten für die Behandlung von Hostingausnahmen zu .NET hinzugefügt. Die BackgroundServiceExceptionBehavior-Enumeration wurde dem Namespace Microsoft.Extensions.Hosting hinzugefügt, um das Verhalten des Diensts bei Auslösen einer Ausnahme anzugeben. Die folgende Tabelle enthält die verfügbaren Optionen:

Option Beschreibung
Ignore In BackgroundServiceausgelöste Ausnahmen werden ignoriert.
StopHost IHost wird beendet, wenn ein Ausnahmefehler ausgelöst wird.

Das Standardverhalten vor .NET 6 ist Ignore, was zu Zombieprozessen (ausgeführten Prozessen, die keinen Zweck erfüllten) führte. Bei .NET 6 ist StopHost das Standardverhalten, sodass der Host bei Auslösen einer Ausnahme beendet wird. Dies geschieht jedoch auf saubere Weise, das heißt, der Dienst wird vom Windows-Dienstverwaltungssystem nicht neu gestartet. Um den Neustart des Diensts ordnungsgemäß zuzulassen, können Sie Environment.Exit mit einem Exitcode ungleich null aufrufen. Betrachten Sie den folgenden hervorgehobenen catch-Block:

namespace App.WindowsService;

public sealed class WindowsBackgroundService(
    JokeService jokeService,
    ILogger<WindowsBackgroundService> logger) : BackgroundService
{
    protected override async Task ExecuteAsync(CancellationToken stoppingToken)
    {
        try
        {
            while (!stoppingToken.IsCancellationRequested)
            {
                string joke = jokeService.GetJoke();
                logger.LogWarning("{Joke}", joke);

                await Task.Delay(TimeSpan.FromMinutes(1), stoppingToken);
            }
        }
        catch (OperationCanceledException)
        {
            // When the stopping token is canceled, for example, a call made from services.msc,
            // we shouldn't exit with a non-zero exit code. In other words, this is expected...
        }
        catch (Exception ex)
        {
            logger.LogError(ex, "{Message}", ex.Message);

            // Terminates this process and returns an exit code to the operating system.
            // This is required to avoid the 'BackgroundServiceExceptionBehavior', which
            // performs one of two scenarios:
            // 1. When set to "Ignore": will do nothing at all, errors cause zombie services.
            // 2. When set to "StopHost": will cleanly stop the host, and log errors.
            //
            // In order for the Windows Service Management system to leverage configured
            // recovery options, we need to terminate the process with a non-zero exit code.
            Environment.Exit(1);
        }
    }
}

Überprüfen der Dienstfunktionalität

Um die als Windows-Dienst erstellte App anzuzeigen, öffnen Sie Dienste. Wählen Sie die Windows-Taste (oder STRG + ESC) aus, und suchen Sie unter „Dienste“. In der App Dienste sollten Sie Ihren Dienst anhand seines Namens finden können.

Wichtig

Standardmäßig können reguläre Benutzer (nicht administratorinterne) Windows-Dienste nicht verwalten. Um zu überprüfen, ob diese App erwartungsgemäß funktioniert, müssen Sie ein Administratorkonto verwenden.

The Services user interface.

Um zu überprüfen, ob der Dienst wie erwartet funktioniert, müssen Sie folgendermaßen vorgehen:

  • Starten des Dienstes
  • Anzeigen der Protokolle
  • Dienst beenden

Wichtig

Stellen Sie zum Debuggen der Anwendung sicher, dass Sie nicht versuchen, die ausführbare Datei zu debuggen, die aktiv innerhalb des Windows Services-Prozesses ausgeführt wird.

Unable to start program.

Starten des Windows-Diensts

Um den Windows-Dienst zu starten, verwenden Sie den sc.exe start-Befehl:

sc.exe start ".NET Joke Service"

Daraufhin wird eine Ausgabe angezeigt, die in etwa wie folgt aussieht:

SERVICE_NAME: .NET Joke Service
    TYPE               : 10  WIN32_OWN_PROCESS
    STATE              : 2  START_PENDING
                            (NOT_STOPPABLE, NOT_PAUSABLE, IGNORES_SHUTDOWN)
    WIN32_EXIT_CODE    : 0  (0x0)
    SERVICE_EXIT_CODE  : 0  (0x0)
    CHECKPOINT         : 0x0
    WAIT_HINT          : 0x7d0
    PID                : 37636
    FLAGS

Der Status des Diensts wechselt von START_PENDING zu Wird ausgeführt.

Anzeigen von Protokollen

Um Protokolle anzuzeigen, öffnen Sie die Ereignisanzeige. Wählen Sie die Windows-Taste (oder STRG + ESC) aus, und suchen Sie nach "Event Viewer". Wählen Sie den Knoten Ereignisanzeige (lokal)>Windows-Protokolle>Anwendung aus. Es sollte ein Eintrag auf der Ebene Warnung mit einer Quelle angezeigt werden, die mit dem Apps-Namespace übereinstimmt. Doppelklicken Sie auf den Eintrag, oder klicken Sie mit der rechten Maustaste, und wählen Sie Ereigniseigenschaften aus, um die Details anzuzeigen.

The Event Properties dialog, with details logged from the service

Nachdem Sie Protokolle im Ereignisprotokoll angezeigt haben, sollten Sie den Dienst beenden. Er ist so konzipiert, dass jede Minute einmal ein zufälliger Scherz protokolliert wird. Dieses Verhalten ist beabsichtigt, aber für Produktionsdienste nicht praktikabel.

Beenden des Windows-Diensts

Beenden Sie den Windows-Dienst mit dem sc.exe stop-Befehl:

sc.exe stop ".NET Joke Service"

Daraufhin wird eine Ausgabe angezeigt, die in etwa wie folgt aussieht:

SERVICE_NAME: .NET Joke Service
    TYPE               : 10  WIN32_OWN_PROCESS
    STATE              : 3  STOP_PENDING
                            (STOPPABLE, NOT_PAUSABLE, ACCEPTS_SHUTDOWN)
    WIN32_EXIT_CODE    : 0  (0x0)
    SERVICE_EXIT_CODE  : 0  (0x0)
    CHECKPOINT         : 0x0
    WAIT_HINT          : 0x0

Der Status des Diensts geht von STOP_PENDING in Stopped (Beendet) über.

Löschen des Windows-Diensts

Verwenden Sie zum Löschen des Windows-Diensts den Löschbefehl („sc.exe“) des nativen Windows-Dienststeuerungs-Managers. Führen Sie PowerShell als Administrator aus.

Wichtig

Wenn sich der Dienst nicht im Zustand Beendet befindet, wird er nicht sofort gelöscht. Stellen Sie sicher, dass der Dienst beendet ist, bevor Sie den Löschbefehl ausführen.

sc.exe delete ".NET Joke Service"

Sie sehen eine Ausgabemeldung:

[SC] DeleteService SUCCESS

Weitere Informationen finden Sie unter sc.exe delete.

Siehe auch

Nächste