Infobereich-Symbole und Toast-Benachrichtigungen in Windows-Apps — Fallstricke von NotifyIcon und die richtige AppNotification-Wahl

· · Infobereich, NotifyIcon, Toast-Benachrichtigungen, AppNotification, Windows App SDK, WinForms, WPF, C#, .NET, Residente Anwendung, Windows-Entwicklung, Technische Beratung

„Ich möchte den Benutzer unauffällig informieren, wenn eine Verarbeitung abgeschlossen ist.” – „Ich möchte, dass die Überwachung auch nach dem Schließen des Fensters weiterläuft.” – Dies sind zwei klassische Anforderungen, die in Geschäftsanwendungen häufig gemeinsam auftreten: die dauerhafte Präsenz im Infobereich (System Tray) und das Versenden von Toast-Benachrichtigungen. Sobald man sie jedoch tatsächlich implementiert, tauchen nacheinander kleine Probleme auf – eine Anwendung, die eigentlich beendet werden sollte, lässt sich nicht wirklich schließen, das Symbol verschwindet nach einem Neustart des Explorers, oder ein Toast, der während der Entwicklung einwandfrei funktionierte, erscheint beim Kunden nie.

Hinzu kommt, dass Toast-Benachrichtigungen ein Bereich sind, in dem sich die API seit der UWP-Ära ständig von Generation zu Generation verändert hat. Es ist nicht ungewöhnlich, online zu recherchieren und Beispielcode zu finden, der nach heutigem Stand eine API verwendet, die bestenfalls nur noch gewartet wird. Dieser Artikel ordnet sowohl das Design der Infobereich-Residenz mit NotifyIcon als auch die Wahl einer Toast-Benachrichtigungs-API ab 2026, zusammen mit den praktischen Fallstricken, auf die Sie wahrscheinlich stoßen werden.

1. Zuerst das Wichtigste

  • Die Grundlage der Infobereich-Residenz ist nach wie vor System.Windows.Forms.NotifyIcon. Es erscheint nur, wenn Sie Icon festlegen und Visible = true setzen (der Standardwert ist false). Der QuickInfo-Text Text kann ab .NET 6 bis zu 127 Zeichen lang sein (davor 63 Zeichen).12
  • WPF verfügt über kein zu NotifyIcon äquivalentes Steuerelement. Die offizielle Vergleichstabelle gibt ausdrücklich „Kein entsprechendes Steuerelement” an. Sowohl UseWPF als auch UseWindowsForms in der csproj zu aktivieren und das NotifyIcon von WinForms zu verwenden, ist die minimale Konfiguration.34
  • „Die App im Infobereich behalten, auch wenn der Benutzer auf die Schaltfläche zum Schließen klickt” wird implementiert, indem e.Cancel = true in FormClosing gesetzt und Hide() aufgerufen wird. Stellen Sie immer einen separaten, expliziten Weg zum Beenden bereit (einen Eintrag „Beenden” im Infobereich-Menü) und prüfen Sie CloseReason, damit Sie niemals ein Herunterfahren des Betriebssystems blockieren.5
  • Die empfohlene Toast-API ist ab 2026 eindeutig. Unabhängig davon, ob Sie eine WinForms-, WPF- oder nicht paketierte Anwendung erstellen, wird der AppNotificationManager des Windows App SDK (NuGet: Microsoft.WindowsAppSDK) empfohlen. Windows.UI.Notifications befindet sich im Status „nur Wartung”, und die Benachrichtigungskomponente des Community Toolkit ist archiviert.67
  • Die AppNotification des Windows App SDK funktioniert sogar von einer einfachen exe ohne Paketidentität aus. AppNotificationManager.Default.Register() übernimmt automatisch die COM-Serverregistrierung und die AUMID-äquivalente Arbeit, sodass Sie keine Verknüpfung im Startmenü mehr einrichten müssen, wie es frühere Generationen erforderten. Allerdings werden Benachrichtigungen von erhöhten (Administrator-)Prozessen nicht unterstützt.8910
  • Ein Toast ist kein garantierter Weg, den Benutzer zu erreichen. Während der Fokusassistent (Nicht stören) aktiv ist, erscheint das Banner nicht und die Benachrichtigung geht direkt an das Info-Center, und der Benutzer kann Benachrichtigungen auch vollständig in den Einstellungen deaktivieren. Ihr Design darf nicht voraussetzen, dass „der Toast angezeigt wurde”, als Vorbedingung für einen Geschäftsablauf.1112
  • Ein Windows-Dienst kann keine Toasts senden (Sitzung 0 hat keine Benutzeroberfläche). Der Standardansatz besteht darin, einen residenten Agenten im Infobereich in der Sitzung des Benutzers zu platzieren und über IPC zu koordinieren.13

2. Grundlagen der Infobereich-Residenz mit NotifyIcon

System.Windows.Forms.NotifyIcon ist die Komponente, die ein Symbol im Infobereich am rechten Ende der Taskleiste platziert. Apps, die im Hintergrund weiterlaufen, nutzen es als Einstiegspunkt für die Statusanzeige und ein Bedienmenü.1

private NotifyIcon _trayIcon = null!;

private void InitializeTrayIcon()
{
    var menu = new ContextMenuStrip();
    menu.Items.Add("Öffnen", null, (_, _) => ShowMainWindow());
    menu.Items.Add(new ToolStripSeparator());
    menu.Items.Add("Beenden", null, (_, _) => ExitApplication());

    _trayIcon = new NotifyIcon
    {
        Icon = Properties.Resources.AppIcon, // Icon ist Pflicht; ohne wird nichts angezeigt
        Text = "Auftragsüberwachungstool ── läuft",     // Tooltip (max. 127 Zeichen ab .NET 6+)
        ContextMenuStrip = menu,
        Visible = true                        // Standardwert ist false; wird erst nach true angezeigt
    };
    _trayIcon.DoubleClick += (_, _) => ShowMainWindow();
}

Drei Punkte sind erwähnenswert.

  • Das Symbol erscheint erst, wenn sowohl Icon als auch Visible = true gesetzt sind. Der Standardwert von Visible ist false.1
  • Text hat eine Längenbeschränkung. Ab .NET 6 sind es maximal 127 Zeichen, bei .NET 5 und früher sowie bei .NET Framework 63 Zeichen; eine Überschreitung löst eine ArgumentException aus. Zu viele Statusinformationen in die QuickInfo zu packen, ist ein guter Weg, damit Ihre App irgendwann plötzlich mit einer Ausnahme abstürzt.214
  • Verknüpfen Sie ein Rechtsklick-Menü über ContextMenuStrip. Das Infobereich-Symbol ist oft der einzige für den Benutzer sichtbare Einstiegspunkt, stellen Sie also mindestens einen Eintrag „Öffnen” und „Beenden” bereit.15

Ein weiterer Punkt: Das Infobereich-Symbol ist nicht nur ein Einstiegspunkt für Benachrichtigungen, sondern auch ein ständig sichtbarer Statusindikator. Da Icon und Text während der Ausführung der App ausgetauscht werden können, bedeutet die Widerspiegelung des aktuellen Zustands – ein normales Symbol im Normalfall, ein Warnsymbol bei einem Problem, die Anzeige der letzten Verarbeitungszeit in der QuickInfo –, dass der Benutzer einen Blick auf das Symbol werfen und den aktuellen Status erkennen kann, selbst wenn er einen Toast verpasst hat. Der Toast ist der Kanal für „etwas ist gerade in diesem Moment passiert”, während das Infobereich-Symbol der Kanal für „so ist der Status gerade jetzt” ist – so ist die Aufgabenteilung.

3. Das Verhalten „Bleibt beim Schließen im Infobereich” gestalten und ein korrekter Beendigungsweg

Ein klassisches Verhalten residenter Apps ist: Ein Klick auf die Schließen-Schaltfläche beendet den Prozess nicht, sondern belässt ihn nur im Infobereich. Die Implementierung selbst lässt sich durch Abbrechen von FormClosing leicht schreiben, aber wenn man sie unachtsam schreibt, führt das zu zwei Arten von Problemen: Es gibt keine Möglichkeit mehr, die App zu beenden, und es blockiert das Herunterfahren von Windows.

private bool _exitRequested;

protected override void OnFormClosing(FormClosingEventArgs e)
{
    // Wenn der Benutzer nur auf X geklickt hat, ausblenden statt schließen
    if (!_exitRequested && e.CloseReason == CloseReason.UserClosing)
    {
        e.Cancel = true;
        Hide();
        return;
    }
    // Normales Schließen über das Menü „Beenden“, Herunterfahren des Betriebssystems usw.
    base.OnFormClosing(e);
}

private void ExitApplication()
{
    _exitRequested = true;
    _trayIcon.Visible = false;
    _trayIcon.Dispose();
    Close();
}

FormClosing wird ausgelöst, bevor das Formular geschlossen wird, und das Setzen von e.Cancel = true bricht das Schließen ab. Prüfen Sie dabei immer CloseReason. Das korrekte Verhalten besteht darin, nur bei UserClosing (einer Benutzeraktion) abzubrechen und niemals bei einem vom Betriebssystem ausgelösten Schließen wie WindowsShutDown abzubrechen.516

WPF folgt derselben Logik: Die offizielle Dokumentation selbst beschreibt das Muster, e.Cancel = true in Window.Closing zu setzen und Hide() aufzurufen.17

Beachten Sie, dass eine residente App aufgrund ihrer Natur immer dem Risiko ausgesetzt ist, dass „bei doppeltem Start dasselbe Ereignis doppelt verarbeitet wird”. Wir haben die Verhinderung mehrfacher Starts in „Mehrfachstarts einer Windows-App verhindern – benannte Mutexe und Aktivierung der laufenden Instanz beim zweiten Start” behandelt. Und „Warum .NET Generic Host und BackgroundService in einer Desktopanwendung verwenden” bildet die Grundlage für den Aufbau des eigentlichen Inhalts einer residenten App – der Überwachungsschleife oder der periodischen Verarbeitung.

4. Infobereich-Residenz in einer WPF-Anwendung

WPF verfügt über kein zu NotifyIcon äquivalentes Steuerelement. Dies ist eine dokumentierte Lücke der Plattform, die in der offiziellen Vergleichstabelle „WPF-Steuerelemente, die WinForms-Steuerelementen entsprechen” ausdrücklich als „No equivalent control” angegeben ist.3

Es gibt zwei realistische Optionen.

Option Übersicht Empfehlung
Das NotifyIcon von WinForms neben WPF verwenden Sowohl UseWPF als auch UseWindowsForms in der csproj aktivieren Keine zusätzliche Abhängigkeit. Ausreichend, wenn nur ein Symbol und ein Menü benötigt werden
Drittanbieter (z. B. H.NotifyIcon) Für WPF/WinUI konzipierte Implementierungen von Infobereich-Symbolen Zu wählen, wenn Sie in XAML schreiben möchten oder ein reichhaltigeres Popup benötigen. Bedenken Sie, dass es sich nicht um eine offizielle Microsoft-Komponente handelt

Die erste Option besteht lediglich darin, zwei Eigenschaften nebeneinander in einer SDK-Style-Projektdatei aufzulisten.4

<PropertyGroup>
  <TargetFramework>net8.0-windows</TargetFramework>
  <UseWPF>true</UseWPF>
  <UseWindowsForms>true</UseWindowsForms>
</PropertyGroup>

Sie können dann einfach ein System.Windows.Forms.NotifyIcon direkt aus einer WPF-Application heraus instanziieren. Nur das Menü landet dann bei WinForms (ContextMenuStrip), aber für etwas so Einfaches wie ein Infobereich-Menü ist das selten ein praktisches Problem.

5. Drei Fallstricke bei Infobereich-Symbolen

5.1. Symbole landen standardmäßig bei den „ausgeblendeten Symbolen” — eine erzwungene Anzeige ist nicht möglich

Die Anforderung, das Symbol Ihrer App dauerhaft in der Taskleiste sichtbar zu halten, kommt immer wieder auf, aber das lässt sich nicht programmatisch umsetzen. Die offizielle Dokumentation stellt klar, dass Symbole standardmäßig im Überlaufbereich (ausgeblendete Symbole) hinzugefügt werden, und dass nur der Benutzer entscheiden kann, ob ein Symbol zur dauerhaften Anzeige im Infobereich hochgestuft wird.18

Unter Windows 11 aktiviert oder deaktiviert der Benutzer dies pro App über „Einstellungen → Personalisierung → Taskleiste → Weitere Symbolbereich-Symbole”. Wenn die dauerhafte Sichtbarkeit betrieblich wichtig ist, besteht der richtige Ansatz darin, dies in Ihrer Installationsanleitung oder Hilfe zu dokumentieren („bitte diese Einstellung aktivieren”), anstatt zu versuchen, sie im Code zu erzwingen.

5.2. Das Symbol verschwindet, wenn der Explorer neu startet — TaskbarCreated

Wenn der Explorer abstürzt oder neu startet und die Taskleiste neu erstellt, verschwinden alle registrierten Infobereich-Symbole. Die Shell sendet beim Erstellen der Taskleiste eine TaskbarCreated-Nachricht an alle Fenster oberster Ebene, und die Konvention auf Win32-Ebene lautet, dass Sie Ihr Symbol beim Empfang dieser Nachricht erneut registrieren sollten.19

Das NotifyIcon von WinForms behandelt diese Nachricht intern und registriert sich automatisch neu, sodass Sie sich normalerweise keine Gedanken darüber machen müssen. Wenn Sie Shell_NotifyIcon selbst per P/Invoke aufrufen (oder eine native App mit einem Infobereich-Symbol pflegen), stellen Sie sicher, dass diese Logik zur Neuregistrierung vorhanden ist. Das Symptom „das Symbol verschwindet nur, wenn der Explorer neu startet, aber der Prozess lebt noch” ist fast immer genau dieses Problem.

5.3. Vergessenes Dispose hinterlässt ein Geister-Symbol

Auf Win32-Ebene muss ein Infobereich-Symbol explizit entfernt werden (NIM_DELETE), sobald es nicht mehr benötigt wird, und in WinForms übernimmt NotifyIcon.Dispose() diese Verantwortung.18 Stellen Sie sicher, dass Ihr Beendigungsweg immer über Visible = falseDispose() verläuft. Jeder Entwickler residenter Apps hat diese Szene schon mindestens einmal gesehen: Der Prozess wird ohne Bereinigung anormal beendet, und ein Geister-Symbol bleibt im Infobereich hängen, bis der Benutzer den Mauszeiger darüber bewegt.

Wie im Code aus Kapitel 3 ist es am sichersten, das Infobereich-Symbol im Handler des „Beenden”-Menüs zu bereinigen, bevor Close() aufgerufen wird.

6. Toast-Benachrichtigungen — welche API sollte man verwenden

Eine Toast-Benachrichtigung ist das Banner, das in der unteren rechten Bildschirmecke erscheint und dann im Info-Center verbleibt. Die Art und Weise, eine solche aus einer Desktopanwendung zu senden, hat sich im letzten Jahrzehnt ständig verändert, und Suchergebnisse sind noch immer voller alter Beispiele. So sieht der Stand ab 2026 aus.6

API NuGet / Namespace Status (Stand 2026) Fazit
Windows App SDK AppNotification Microsoft.WindowsAppSDK / Microsoft.Windows.AppNotifications Offiziell empfohlen für WinForms, WPF und nicht paketiertes Win32 Für Neuentwicklungen verwenden
Community Toolkit Notifications Microsoft.Toolkit.Uwp.Notifications Archiviert. Nicht mehr Teil des aktuellen Community Toolkit; letzte Aktualisierung 2022 Nur zur Pflege bestehenden Codes. Nicht für neue Projekte übernehmen
Direkte WinRT-Nutzung Windows.UI.Notifications (über den Windows-TFM) Nur Wartung. Hauptsächlich für UWP empfohlen Nicht für neue Projekte übernehmen
NotifyIcon.ShowBalloonTip System.Windows.Forms API für Sprechblasenbenachrichtigungen. Wird unter Windows 10 als Toast dargestellt; unter Windows 11 handelt es sich um eine temporäre Anzeige, die nicht im Info-Center verbleibt Für einfache Zwecke geeignet, aber beachten Sie, dass sich das Verhalten je nach Betriebssystemversion ändert

Zwei weitere Anmerkungen.

  • ShowBalloonTip gehört zu jenen Fällen „alte API, aber tatsächlich noch lebendig”. Unter Windows 10 werden Sprechblasen als Toast dargestellt und bleiben bis zum Schließen im Info-Center. Unter Windows 11 hingegen verhalten sie sich eher wie eine traditionelle temporäre Sprechblase und bleiben nach dem Verschwinden nicht im Info-Center erhalten. Auch die Angabe der Anzeigedauer (Timeout) wird inzwischen ignoriert und richtet sich stattdessen nach den Barrierefreiheitseinstellungen des Betriebssystems. Das reicht für eine im Infobereich resident laufende App völlig aus, die nur leicht auf eine Zustandsänderung hinweisen möchte, aber wenn Sie möchten, dass ein Verlauf im Info-Center erhalten bleibt, denken Sie daran, dass Ihnen das unter Windows 11 nicht hilft.20
  • Der klassische Ansatz, das reine Windows.UI.Notifications aus einer Desktopanwendung heraus zu verwenden, hat eine bekannte Einschränkung: Der Toast wird nicht angezeigt, solange Sie nicht eine Verknüpfung mit einer AUMID (AppUserModelID) im Startmenü registriert haben.21 Die AppNotification, die im nächsten Kapitel behandelt wird, ist genau das, was diesen Ärger beseitigt.

7. Eine minimale Implementierung von Windows App SDK AppNotification

Die App-Benachrichtigungs-API des Windows App SDK funktioniert sogar von einer einfachen, nicht paketierten exe aus, ohne Paketidentität.8 Die Voraussetzungen auf Projektseite sind ein Windows-spezifischer TFM (z. B. net8.0-windows10.0.19041.0), <WindowsPackageType>None</WindowsPackageType> (für den nicht paketierten Fall) und das Vorhandensein der Windows App SDK-Runtime am Bereitstellungsziel.9

using Microsoft.Windows.AppNotifications;
using Microsoft.Windows.AppNotifications.Builder;

// Einmalig beim Start; die Reihenfolge Handler-Registrierung → Register() ist wichtig
AppNotificationManager.Default.NotificationInvoked += (_, args) =>
{
    // Toast-Klicks und Schaltflächenklicks landen hier (Unterscheidung über args.Arguments)
    if (args.Arguments.TryGetValue("action", out var action) && action == "openLog")
    {
        ShowLogWindow();
    }
};
AppNotificationManager.Default.Register();

// Benachrichtigung anzeigen
var notification = new AppNotificationBuilder()
    .AddText("Auftragsimport abgeschlossen")
    .AddText("12 neu, 1 Fehler")
    .AddButton(new AppNotificationButton("Protokoll öffnen")
        .AddArgument("action", "openLog"))
    .BuildNotification();
AppNotificationManager.Default.Show(notification);

Die praktischen Punkte, auf die zu achten ist:

  • Abonnieren Sie NotificationInvoked, bevor Sie Register() aufrufen. Machen Sie diese Reihenfolge falsch, verpassen Sie das Ereignis, wenn ein Klick auf den Toast die App startet.9
  • Rufen Sie AppNotificationManager.Default.Unregister() auf, bevor die App beendet wird. Die offizielle Dokumentation gibt ausdrücklich an, dass der Aufruf von Unregister vor dem Beenden Ressourcen bereinigt und sicherstellt, dass die App beim nächsten Klick auf eine Benachrichtigung korrekt gestartet wird. Bauen Sie dies in den Handler des „Beenden”-Menüs aus Kapitel 3 ein, neben NotifyIcon.Dispose() (es gibt auch ein separates UnregisterAll() für Fälle wie das Deinstallieren einer App, die Benachrichtigungen nie wieder verwenden wird, das die Registrierungsinformationen vollständig löscht).22
  • Bei nicht paketierten Apps übernimmt Register() automatisch die COM-Serverregistrierung und die AUMID-äquivalente Arbeit. Die Einrichtung einer Verknüpfung oder die Registry-Registrierung, die von der älteren Generation, dem reinen WinRT, benötigt wurde, ist nicht mehr erforderlich. Wenn Sie stattdessen mit MSIX paketieren, müssen Sie umgekehrt den COM-Aktivator in Package.appxmanifest deklarieren.9
  • Seien Sie vorsichtig, wenn Sie eine eigenständige (self-contained) Bereitstellung wählen, die die Windows App SDK-Runtime mitliefert. AppNotificationManager hängt vom Singleton-Paket des Windows App SDK ab, und es gibt offiziell dokumentierte Überlegungen für den Aufruf aus einer eigenständigen App. Prüfen Sie dies, bevor Sie sich auf eine Bereitstellungsmethode festlegen.23
  • Benachrichtigungen von erhöhten (Administrator-)Prozessen werden nicht unterstützt. Show löst keine Ausnahme aus, sondern schlägt einfach stillschweigend fehl, was die eigentliche Ursache schwer erkennbar macht. Für Apps, die eine Erhöhung benötigen, sollten Sie in Betracht ziehen, nur die Benachrichtigung in einen nicht erhöhten Prozess auszulagern (dieser Isolationsansatz wird in „Ein konkreter Weg, in einer Windows-App nur die Vorgänge zu isolieren, die Administratorrechte erfordern” behandelt).10
  • Wenn ein Toast angeklickt wird und die App derzeit nicht ausgeführt wird, wird ein neuer Prozess gestartet. In einer im Infobereich residenten App müssen Sie dies mit der Verhinderung mehrfacher Instanzen (Kapitel 3) kombinieren, sodass die Arbeit an die vorhandene Instanz übergeben wird.

8. Fortgeschrittene Verwendung — Toasts mit Fortschrittsbalken und Bereinigung von Benachrichtigungen

8.1. Fortschritt innerhalb eines Toasts aktualisieren — UpdateAsync

Bei einer lange laufenden Verarbeitung wie „Import von 120 Bestelldatensätzen” besteht der richtige Ansatz nicht darin, wiederholt eine neue Benachrichtigung auszulösen, sondern den Fortschrittsbalken innerhalb eines einzigen Toasts zu aktualisieren. AppNotification verfügt über einen Datenbindungs- und Aktualisierungsmechanismus, der genau dafür konzipiert ist.24

Der Aufbau erfolgt in drei Schritten. Verwandeln Sie zuerst jeden Wert des Fortschrittsbalkens mit den Bind-Methoden in einen Platzhalter, geben Sie der Benachrichtigung über Tag (und bei Bedarf Group) eine Identität und zeigen Sie sie an. Danach müssen Sie nur noch ein AppNotificationProgressData an UpdateAsync übergeben, und nur der Inhalt des bereits angezeigten Toasts wird neu geschrieben.

const string tag = "import-progress";
const string group = "batch";

// Erste Anzeige: Wert binden und den Anfangswert bei Progress setzen
var notification = new AppNotificationBuilder()
    .AddText("Auftragsdaten werden importiert")
    .AddProgressBar(new AppNotificationProgressBar()
        .BindStatus().BindValue().BindValueStringOverride())
    .SetTag(tag)
    .SetGroup(group)
    .BuildNotification();

notification.Progress = new AppNotificationProgressData(1) // Sequenznummer
{
    Status = "Wird importiert...", Value = 0, ValueStringOverride = "0/120 Einträge"
};
AppNotificationManager.Default.Show(notification);

// Bei jedem Fortschritt: Sequenznummer erhöhen und aktualisieren
var data = new AppNotificationProgressData(2)
{
    Status = "Wird importiert...", Value = 45 / 120.0, ValueStringOverride = "45/120 Einträge"
};
await AppNotificationManager.Default.UpdateAsync(data, tag, group);

Die Sequenznummer ist eine ganze Zahl ungleich null, die die Aktualisierungsreihenfolge angibt; kommen mehrere Aktualisierungen außer der Reihe an, gewinnt diejenige mit der höchsten Nummer. Dies existiert, damit gleichzeitige Aktualisierungen aus asynchroner Verarbeitung nicht auf einen veralteten Wert zurückfallen, achten Sie daher darauf, dass sie immer monoton ansteigt.25

8.2. „Aktualisieren” versus „Ersetzen” — wann welches verwendet werden sollte

Sie können das Erscheinungsbild auch aktualisieren, indem Sie eine neue Benachrichtigung mit demselben Tag erneut anzeigen (Show) — ein „Ersetzen” — aber das Verhalten unterscheidet sich von einem „Aktualisieren”.24

  Ersetzen (erneutes Show mit demselben Tag) Aktualisieren (UpdateAsync)
Position im Info-Center Bewegt sich nach oben Bleibt an Ort und Stelle
Was geändert werden kann Alles, einschließlich des Layouts Nur der gebundene Fortschrittsbalken und der vorangestellte Text
Popup Kann erneut aufpoppen Poppt nicht erneut auf (wird still neu geschrieben)
Wenn der Benutzer sie bereits geschlossen hat Wird immer zugestellt Schlägt fehl

Die offizielle Empfehlung ist auch hier eindeutig: Aktualisieren für Zwischenfortschritt, Ersetzen beim Abschluss. Es ist nicht nötig, bei jedem Fortschrittsschritt von 50 % auf 65 % ein Popup anzuzeigen, aber „Import abgeschlossen (3 Fehler)” sollte den Benutzer auch dann erreichen, wenn er die Fortschrittsbenachrichtigung bereits geschlossen hat. In der Praxis besteht das gängige Muster darin, den Fortschrittsbalken beim Abschluss zu entfernen und ihn durch ein anderes Layout mit Schaltflächen zu ersetzen, etwa „Fehlerdetails anzeigen”.

8.3. Alte Benachrichtigungen bereinigen, die im Info-Center verbleiben

Toasts sammeln sich im Info-Center an, bis der Benutzer sie löscht. Wenn eine residente App jeden Tag mehrere Benachrichtigungen sendet, füllt sich das Info-Center mit alten Benachrichtigungen Ihrer App, wodurch am Ende wichtige Benachrichtigungen begraben werden können.

Das Anhängen von Tag / Group erlaubt es Ihnen, Benachrichtigungen Ihrer eigenen App programmatisch zu löschen (nach Tag, nach Gruppe oder alle). Sie können auch ein Ablaufdatum festlegen. Es lohnt sich, Ihre Bereinigungsregeln — „Fortschritts-Benachrichtigungen bei Abschluss löschen”, „Ablaufzeit für informative Benachrichtigungen verkürzen” — gleichzeitig mit dem Entwurf festzulegen, wie Benachrichtigungen gesendet werden.26

9. Design für die Fälle, in denen eine Benachrichtigung „nicht ankommt”

Eine Toast-Benachrichtigung ist kein garantierter Zustellungsmechanismus. Es gibt völlig normale Pfade, auf denen sie nicht angezeigt oder nicht bemerkt wird.

Fall Verhalten
Fokusassistent (Nicht stören) ist aktiviert Das Banner wird nicht angezeigt; die Benachrichtigung geht direkt an das Info-Center
Benachrichtigungen sind deaktiviert, pro App oder systemweit Es wird nichts angezeigt
AppNotification von einem erhöhten Prozess Nicht unterstützt. Es wird nichts angezeigt
Eine Vollbild-App wird ausgeführt usw. Das Betriebssystem kann sie nach eigenem Ermessen unterdrücken

Nicht stören heißt unter Windows 10 „Fokusassistent (Focus assist)” und wird unter Windows 11 über den Schalter „Nicht stören” unter „Einstellungen → System → Benachrichtigungen” gesteuert; es kann vom Benutzer oder per Gruppenrichtlinie geregelt werden. Es gibt sogar eine Regel, wonach es in der ersten Stunde nach einem Betriebssystem-Upgrade automatisch aktiviert wird.11 Der Fokusassistent bedeutet nicht „keine Benachrichtigungen senden”, sondern „das Banner unterdrücken und direkt an das Info-Center weiterleiten” — der Benutzer wird sie also trotzdem sehen, wenn er später das Info-Center öffnet.12

Die Design-Implikation ist einfach:

  • Behandeln Sie den Toast als ergänzenden Kanal, der Benutzern hilft, schneller zu reagieren, falls sie ihn bemerken, und stellen Sie sicher, dass für den Geschäftsprozess zwingende Informationen immer auf einem Bildschirm oder in einer Liste innerhalb der App bestätigt werden können. Bauen Sie keinen Arbeitsablauf, der davon ausgeht, dass „der Toast vermutlich angezeigt wurde”.
  • Für Benachrichtigungen, die den Benutzer unbedingt unterbrechen müssen (wie eine Notabschaltungswarnung), gibt es einen Mechanismus, um mit Zustimmung des Benutzers das Nicht-stören-Modus über AppNotificationScenario.Urgent zu durchbrechen,27 aber übermäßiger Gebrauch führt dazu, dass Benutzer die Benachrichtigungen Ihrer App vollständig deaktivieren. Beschränken Sie dies nur auf wirklich dringende Fälle.

Für die breitere Frage, wie man Dinge wie Fehler externer Geräte auf dem Bildschirm darstellt, siehe auch „Best Practices für die Prüfung und Anzeige des Status externer Geräte”.

10. Wenn Sie aus einem Windows-Dienst benachrichtigen müssen

Es ist eine natürliche Anforderung: „Wenn ein residenter Dienst ein Problem erkennt, möchte ich den angemeldeten Benutzer per Toast benachrichtigen” — aber ein Dienst kann keinen Toast direkt senden. Seit Windows Vista laufen Dienste in einer dedizierten Sitzung namens Sitzung 0 und haben keine Möglichkeit, eine mit dem Benutzer interagierende Benutzeroberfläche anzuzeigen.13

Der Standardansatz besteht darin, die Benutzeroberfläche in einen Prozess auszulagern, der in der Sitzung des Benutzers läuft.

[Sitzung 0]                        [Benutzersitzung]
 Windows-Dienst   <-- IPC -->   Im Infobereich residenter Agent
 (Überwachung/Geschäftslogik)   Benannte Pipes usw.   (NotifyIcon + AppNotification)

In Umgebungen, in denen mehrere Benutzer gleichzeitig angemeldet sind (RDP, gemeinsam genutzte Terminals), läuft der Agent am Ende einmal pro Sitzung. Im Voraus als Anforderung festzulegen, „wer benachrichtigt werden soll” (alle oder nur ein bestimmter Benutzer), macht das Design stabiler.

11. Zusammenfassung

  • Die Infobereich-Residenz basiert auf NotifyIcon. Zeigen Sie es über Icon + Visible = true an, halten Sie Text innerhalb der 127-Zeichen-Grenze (.NET 6+), und stellen Sie sicher, dass Dispose() im Beendigungsweg zuverlässig aufgerufen wird. Verwenden Sie das Symbol und die QuickInfo auch als ständig sichtbaren Indikator für den aktuellen Zustand.
  • „Beim Schließen mit der ×-Schaltfläche im Infobereich bleiben” wird implementiert, indem FormClosing abgebrochen wird, aber brechen Sie nur bei CloseReason.UserClosing ab und stellen Sie immer ein explizites „Beenden”-Menü bereit.
  • Nur der Benutzer kann entscheiden, ob ein Symbol immer sichtbar ist. Behandeln Sie das Verschwinden des Symbols bei Explorer-Neustarts durch erneute Registrierung bei TaskbarCreated (WinForms erledigt dies automatisch).
  • Für jede Neuentwicklung von Toast-Benachrichtigungen ist der AppNotificationManager des Windows App SDK die einzig sinnvolle Wahl. Er funktioniert sogar von einer nicht paketierten exe ohne Paketidentität aus, und Register() automatisiert die mühsame Registrierungsarbeit. Community-Toolkit-Benachrichtigungen sind archiviert, und reines WinRT befindet sich nur im Wartungsstatus.
  • Schreiben Sie für den Zwischenfortschritt einer lange laufenden Verarbeitung den Fortschrittsbalken innerhalb eines einzigen Toasts mit UpdateAsync still neu, und verwenden Sie beim Abschluss ein Ersetzen, um ein Popup anzuzeigen — das ist das Standardmuster. Hängen Sie ein Tag/Group an und beziehen Sie die Bereinigung alter Benachrichtigungen in Ihr Design ein.
  • Ein Toast ist ein ergänzender Kanal, der aufgrund von Nicht stören oder deaktivierten Benachrichtigungen nicht ankommen kann. Gestalten Sie so, dass zwingend erforderliche Informationen immer innerhalb der App bestätigt werden können, und beachten Sie, dass Benachrichtigungen von erhöhten Prozessen nicht unterstützt werden.
  • Benachrichtigungen von einem Dienst werden über die Trennungsarchitektur eines im Infobereich residenten Agenten auf Benutzersitzungsseite plus IPC realisiert.

Verwandte Artikel

Verwandte Beratungsbereiche

Die KomuraSoft LLC (合同会社小村ソフト) übernimmt Design und Implementierung von im Infobereich residenten Überwachungstools und Benachrichtigungs-Agenten, die Architekturprüfung residenter Systeme in Kombination mit Windows-Diensten sowie die Fehlerbehebung bei bestehenden residenten Apps.

Referenzen

  1. Microsoft Learn, NotifyIcon Class / NotifyIcon.Visible Property. Dazu, dass NotifyIcon die Komponente ist, die ein Symbol im Infobereich anzeigt, dass die Icon-Eigenschaft gesetzt werden muss, und dass Visible standardmäßig false ist.  2 3

  2. Microsoft Learn, NotifyIcon.Text Property. Zur Begrenzung des QuickInfo-Texts und zur bei Überschreitung ausgelösten ArgumentException.  2

  3. Microsoft Learn, Windows Forms Controls and Equivalent WPF Controls. Dazu, dass WPF über kein zu NotifyIcon äquivalentes Steuerelement verfügt.  2

  4. Microsoft Learn, MSBuild properties for .NET desktop projects. Dazu, dass sowohl UseWPF als auch UseWindowsForms gemeinsam aktiviert werden können.  2

  5. Microsoft Learn, Form.FormClosing Event. Dazu, dass das Ereignis vor dem Schließen des Formulars ausgelöst wird und Cancel das Abbrechen des Schließens ermöglicht.  2

  6. Microsoft Learn, Windows notifications overview. Tabelle der empfohlenen Benachrichtigungs-API nach App-Typ, einschließlich der Windows-App-SDK-Empfehlung für WinForms/WPF/nicht paketiertes Win32 und des Status „nur Wartung” von Windows.UI.Notifications.  2

  7. Microsoft Learn, Windows Community Toolkit — Notifications (archive). Zur Archivierung der Notifications-Komponente, die durch App-Benachrichtigungen des Windows App SDK ersetzt wurde. 

  8. Microsoft Learn, Use the Windows App SDK in an existing project. Dazu, dass die App-Benachrichtigungs-API des Windows App SDK sowohl paketierte als auch nicht paketierte Apps unterstützt, ohne eine Paketidentität zu erfordern.  2

  9. Microsoft Learn, Quickstart: App notifications in the Windows App SDK. Zur Verwendung von AppNotificationManager/AppNotificationBuilder, zur automatischen Registrierung über Register() bei nicht paketierten Apps, zur Notwendigkeit, NotificationInvoked vor Register() zu abonnieren, und zu Manifest-Deklarationen für paketierte Apps.  2 3 4

  10. Microsoft Learn, App notifications overview. Dazu, dass das Senden von Benachrichtigungen aus einer erhöhten App nicht unterstützt wird.  2

  11. Microsoft Learn, Notifications don’t appear or aren’t displayed. Zur Unterdrückung von Benachrichtigungen durch Nicht stören (Quiet Hours / Focus Assist), zur automatischen Aktivierung in der ersten Stunde nach einem Betriebssystem-Upgrade und zu Prüfschritten, wenn Benachrichtigungen nicht angezeigt werden.  2

  12. Microsoft Learn, Focus assist. Dazu, dass der Fokusassistent die Banneranzeige der Benachrichtigung unterdrückt und sie direkt an das Info-Center weiterleitet.  2

  13. Microsoft Learn, Service Changes for Windows Vista / Interactive Services. Dazu, dass Sitzung 0 ausschließlich für Dienste bestimmt ist und keine Interaktion mit einem Benutzer unterstützt, und zur Empfehlung, CreateProcessAsUser zu verwenden, um einen Prozess in der Sitzung des Benutzers zu erstellen und über IPC zu koordinieren, um dem Benutzer etwas anzuzeigen.  2

  14. Microsoft Learn, NotifyIcon.Text maximum text length increased. Zur bahnbrechenden Änderung in .NET 6, die die maximale Länge von Text von 63 auf 127 Zeichen erweitert hat. 

  15. Microsoft Learn, How to associate a shortcut menu with a Windows Forms NotifyIcon component. Zur Verknüpfung eines Rechtsklick-Menüs über ContextMenuStrip. 

  16. Microsoft Learn, FormClosingEventArgs Class. Dazu, dass CloseReason es ermöglicht, den Grund für das Schließen des Formulars zu bestimmen. 

  17. Microsoft Learn, How to close a window or dialog box (WPF). Zum WPF-Closing-Ereignismuster, e.Cancel = true zu setzen und Hide() aufzurufen, um zu verstecken statt zu schließen. 

  18. Microsoft Learn, Notification Area (Windows Shell). Dazu, dass Symbole standardmäßig dem Überlaufbereich hinzugefügt werden, dass nur der Benutzer ein Symbol zum Infobereich hochstufen kann, und zur Notwendigkeit, nicht mehr benötigte Symbole über NIM_DELETE zu entfernen.  2

  19. Microsoft Learn, The Taskbar. Zur Übertragung der TaskbarCreated-Nachricht beim Erstellen der Taskleiste und dazu, dass man sein Infobereich-Symbol beim Empfang erneut registrieren sollte. 

  20. Microsoft Learn, Shell_NotifyIconW function. Dazu, dass Sprechblasenbenachrichtigungen unter Windows 10 als Toast (Banner) dargestellt werden und im Info-Center verbleiben, unter Windows 11 eine temporäre Anzeige darstellen, die nicht im Info-Center verbleibt, und dass die Anzeigedauer den Barrierefreiheitseinstellungen folgt. 

  21. Microsoft Learn, Send a local toast notification from a C# app (Win32/klassische API). Zur Anforderung, bei Verwendung des reinen ToastNotificationManager eine Verknüpfung mit AUMID im Startmenü zu registrieren. 

  22. Microsoft Learn, AppNotificationManager.Register Method. Zur Notwendigkeit, Unregister vor dem Beenden der App aufzurufen, um Ressourcen zu bereinigen und sicherzustellen, dass nachfolgende Benachrichtigungsstarts korrekt funktionieren, und zur Verwendung von UnregisterAll, um Registrierungsinformationen zu löschen, wenn Benachrichtigungen nie wieder verwendet werden. 

  23. Microsoft Learn, AppNotificationManager.UpdateAsync Method / Windows App SDK deployment architecture. Dazu, dass die Klasse AppNotificationManager vom Singleton-Paket des Windows App SDK abhängt, und zu den Überlegungen für den Aufruf aus einer eigenständigen (self-contained) App. 

  24. Microsoft Learn, App notification progress bar and data binding. Zur Datenbindung über Bind-Methoden, zur Aktualisierung über AppNotificationProgressData und UpdateAsync, sowie zu den Unterschieden zwischen Aktualisieren und Ersetzen (Position im Info-Center, was geändert werden kann, erneutes Aufpoppen des Popups und Verhalten, nachdem der Benutzer sie geschlossen hat), und dazu, dass beim Abschluss ein Ersetzen in Betracht gezogen werden sollte.  2

  25. Microsoft Learn, AppNotificationProgressData(UInt32) Constructor. Dazu, dass die Sequenznummer eine ganze Zahl ungleich null ist, die die Aktualisierungsreihenfolge festlegt, wobei bei Empfang mehrerer Aktualisierungsdaten die Daten mit der höchsten Nummer angezeigt werden. 

  26. Microsoft Learn, Remove app notifications. Zum Anhängen von Tags/Gruppen, zum Entfernen bereits angezeigter Benachrichtigungen und zum Festlegen eines Ablaufdatums. 

  27. Microsoft Learn, App notification content. Zum Vorrang wichtiger Benachrichtigungen mit scenario=”urgent” vor den Nicht-stören-Einstellungen, mit Zustimmung des Benutzers. 

Aktuelle Artikel mit denselben Schlagwörtern führen zu verwandten Themen weiter.

Diese Seiten ordnen den Artikel in einen größeren Leistungs- und Entscheidungskontext ein.

Dieser Artikel ist direkt mit den folgenden Leistungen verbunden.

Häufige Fragen

Fragen, die in Beratungen zu diesem Artikelthema häufig gestellt werden.

Wie erstellt man eine im Infobereich residente Anwendung mit WPF?
WPF verfügt über kein zu NotifyIcon äquivalentes Steuerelement, daher besteht die minimale Konfiguration darin, sowohl UseWPF als auch UseWindowsForms in der csproj zu aktivieren und das NotifyIcon von WinForms zu verwenden. Wenn Sie einen XAML-freundlichen Schreibstil wünschen, ist eine Drittanbieter-Bibliothek wie H.NotifyIcon eine Option, bedenken Sie jedoch bei der Entscheidung, dass es sich nicht um eine offizielle Microsoft-Komponente handelt.
Welche API sollte für Toast-Benachrichtigungen verwendet werden?
Für jede Neuentwicklung ab 2026 wird unabhängig davon, ob Sie eine WinForms-, WPF- oder nicht paketierte Anwendung erstellen, offiziell der AppNotificationManager des Windows App SDK empfohlen. Microsoft.Toolkit.Uwp.Notifications ist archiviert und nicht mehr Teil des aktuellen Community Toolkit, während sich der ToastNotificationManager von WinRT nun im reinen Wartungsstatus befindet. Wenn Ihr bestehender Code bereits mit einer dieser beiden Optionen funktioniert, besteht kein Grund zur Eile bei einer Neufassung, aber es gibt keinen Grund, sie für ein neues Projekt zu wählen.
Was sollte man prüfen, wenn eine Toast-Benachrichtigung nicht angezeigt wird?
Beginnen Sie mit den Einstellungen des Betriebssystems. Wenn der Fokusassistent (Nicht stören) aktiviert ist, werden Benachrichtigungen nicht als Banner angezeigt, sondern gehen direkt an das Info-Center; außerdem können Benachrichtigungen in der Einstellungen-App pro App oder systemweit deaktiviert werden. Auf der Implementierungsseite sind die beiden häufigsten Ursachen, dass AppNotification nicht unterstützt wird, wenn sie von einem erhöhten (Administrator-)Prozess gesendet wird, und dass das reine Windows.UI.Notifications beim Aufruf aus einer Desktopanwendung ohne AUMID nichts anzeigt.
Kann ein Windows-Dienst Toast-Benachrichtigungen senden?
Nein, das ist nicht möglich. Seit Windows Vista laufen Dienste in Sitzung 0 und haben keine Möglichkeit, eine Benutzeroberfläche zur Interaktion mit dem Benutzer anzuzeigen. Wenn Sie den Benutzer benachrichtigen müssen, besteht das Standardmuster darin, einen residenten Agentenprozess im Infobereich innerhalb der Benutzersitzung zu platzieren und ihn über IPC wie benannte Pipes mit dem Dienst kommunizieren zu lassen, wobei der Agent selbst für die Anzeige der Benachrichtigung zuständig ist.

Autorenprofil

Profilseite des Artikelautors.

Go Komura

Geschäftsführer von KomuraSoft LLC

Spezialisiert auf Windows-Softwareentwicklung, technische Beratung und Fehleranalyse, insbesondere bei bestehenden Systemen und schwer reproduzierbaren Störungen.

Öffentliche Links

Zurück zum Blog