Windows-Entwicklung

Single-Instance-Anwendungen in Windows: Mutex, Named Pipes und Code-Beispiele

Das Single-Instance-Muster beschreibt eine Entwurfsentscheidung in der Windows-Anwendungsentwicklung: Eine Anwendung soll zu einem gegebenen Zeitpunkt nur in einer einzigen Instanz im System laufen. Versucht der Benutzer, die Anwendung ein zweites Mal zu öffnen, bringt die neue Instanz das bereits laufende Fenster in den Vordergrund und beendet sich selbst.

Dieses Verhalten ist für viele Desktop-Programme selbstverständlich: Mediaplayer, Notiz-Apps, Konfigurations-Tools – all diese Programme öffnen sich nicht doppelt, sondern wechseln zur laufenden Instanz.

Warum Single-Instance implementieren?

Die Gründe für das Single-Instance-Muster sind vielfältig:

  • Datenkonsistenz – Zwei Instanzen, die dieselbe Datei oder Datenbank öffnen, können sich gegenseitig überschreiben
  • Ressourcenschonung – Unnötige Prozesse verbrauchen RAM und CPU
  • Benutzerfreundlichkeit – Der Anwender erwartet, zur laufenden Instanz geführt zu werden
  • Lizenzkontrolle – Einige Anwendungen erlauben pro Gerät nur eine aktive Sitzung

Methode 1: Mutex (empfohlen)

Die Mutex-Methode (Mutual Exclusion Object) ist die zuverlässigste und am häufigsten verwendete Technik. Ein benannter Mutex ist systemweit sichtbar und kann von mehreren Prozessen gelesen werden.

C++ Implementierung:

#include <windows.h>

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE, LPSTR, int nCmdShow) {
    HANDLE hMutex = CreateMutex(NULL, TRUE, L"Global\MyApp_SingleInstance");

    if (GetLastError() == ERROR_ALREADY_EXISTS) {
        // Instanz läuft bereits – Fenster in den Vordergrund holen
        HWND hWnd = FindWindow(NULL, L"Meine Anwendung");
        if (hWnd) {
            ShowWindow(hWnd, SW_RESTORE);
            SetForegroundWindow(hWnd);
        }
        CloseHandle(hMutex);
        return 0;
    }

    // Normale Initialisierung der Anwendung
    // ...

    CloseHandle(hMutex);
    return 0;
}

C# / .NET Implementierung:

using System.Threading;

static class Program {
    static void Main() {
        bool createdNew;
        using var mutex = new Mutex(true, "Global\MyApp_SingleInstance", out createdNew);

        if (!createdNew) {
            // Andere Instanz läuft bereits
            var hWnd = FindExistingWindow();
            if (hWnd != IntPtr.Zero) {
                ShowWindow(hWnd, SW_RESTORE);
                SetForegroundWindow(hWnd);
            }
            return;
        }

        Application.Run(new MainForm());
    }
}

Methode 2: Named Pipe mit Datenübergabe

Named Pipes ermöglichen nicht nur die Erkennung einer laufenden Instanz, sondern auch die Übergabe von Kommandozeilenargumenten an diese Instanz. Das ist besonders nützlich, wenn die zweite Instanz eine Datei öffnen soll, die die erste Instanz dann lädt.

// Prüfen, ob Named Pipe bereits existiert
HANDLE hPipe = CreateFile(
    L"\\.\pipe\MyApp_Pipe",
    GENERIC_WRITE, 0, NULL,
    OPEN_EXISTING, 0, NULL
);

if (hPipe != INVALID_HANDLE_VALUE) {
    // Instanz läuft – Argumente senden
    DWORD written;
    WriteFile(hPipe, commandLine, strlen(commandLine), &written, NULL);
    CloseHandle(hPipe);
    return 0;
}

// Pipe erstellen und auf Verbindungen warten (Serverseite)
HANDLE hServer = CreateNamedPipe(
    L"\\.\pipe\MyApp_Pipe",
    PIPE_ACCESS_INBOUND,
    PIPE_TYPE_BYTE | PIPE_WAIT,
    1, 256, 256, 0, NULL
);

Methode 3: FindWindow (vereinfacht)

Die einfachste, aber auch unzuverlässigste Methode sucht nach einem Fenster mit einem bekannten Klassennamen:

HWND hWnd = FindWindow(L"MyAppWindowClass", NULL);
if (hWnd != NULL) {
    SetForegroundWindow(hWnd);
    return 0;
}

Diese Methode scheitert, wenn der Fenstername lokalisiert wurde oder kein Fenster angezeigt wird (Tray-Anwendungen).

Vergleich der Methoden

Methode Zuverlässigkeit Datenübergabe Aufwand
Mutex (benannt) Hoch Nein Niedrig
Named Pipe Hoch Ja Mittel
FindWindow Niedrig Über WM_COPYDATA Niedrig
Semaphore (benannt) Hoch Nein Niedrig

Häufig gestellte Fragen

Was ist das Single-Instance-Muster in Windows-Anwendungen?

Das Single-Instance-Muster verhindert, dass eine Windows-Anwendung mehrfach gleichzeitig gestartet wird. Versucht der Benutzer, eine zweite Instanz zu öffnen, wird das Fenster der laufenden Instanz in den Vordergrund gebracht und die neue Instanz beendet sich sofort.

Welche Methode ist am besten für Single-Instance unter Windows?

Die Mutex-Methode mit einem benannten, systemweit sichtbaren Mutex ist die empfohlene Standardlösung. Sie ist einfach zu implementieren, zuverlässig und funktioniert für alle Windows-Anwendungstypen. Named Pipes sind zu bevorzugen, wenn Kommandozeilenargumente an die laufende Instanz übergeben werden müssen.

Wie implementiert man Single-Instance in C# / .NET?

In C# nutzt man System.Threading.Mutex mit einem globalen Namen: new Mutex(true, "Global\AppName", out bool createdNew). Wenn createdNew false ist, läuft bereits eine Instanz. Windows Forms-Anwendungen können alternativ Microsoft.VisualBasic.ApplicationServices.WindowsFormsApplicationBase mit IsSingleInstance = true verwenden.

Was ist der Unterschied zwischen einem lokalen und einem globalen Mutex?

Ein Mutex mit dem Präfix Global ist über alle Windows-Sitzungen (Terminal Services, Remote Desktop) sichtbar. Ein lokaler Mutex (ohne Präfix) gilt nur innerhalb derselben Sitzung. Für Single-Instance-Anwendungen wird in der Regel Global empfohlen.

Kann man mit Named Pipes Daten an eine laufende Instanz senden?

Ja. Named Pipes ermöglichen eine bidirektionale Kommunikation zwischen Prozessen. Die laufende Instanz erstellt eine Named Pipe als Server, die neue Instanz verbindet sich als Client, sendet die Argumente (z. B. Dateipfad) und beendet sich. Die laufende Instanz wertet die Daten aus und reagiert entsprechend.

Wie bringt man das vorhandene Fenster nach vorne, wenn eine neue Instanz gestartet wird?

Die Windows-API-Funktion SetForegroundWindow(hWnd) hebt das Fenster in den Vordergrund. Zuvor sollte ShowWindow(hWnd, SW_RESTORE) aufgerufen werden, um minimierte Fenster wiederherzustellen. Für den Fenstereigentümer können AttachThreadInput oder AllowSetForegroundWindow nötig sein, um Fokus-Sperren zu überwinden.

Funktioniert das Single-Instance-Muster auch bei Diensten (Windows Services)?

Windows-Dienste werden vom Service Control Manager verwaltet und automatisch als Single-Instance behandelt. Das Muster ist für gewöhnliche Desktop-Anwendungen oder Tray-Anwendungen relevant. Bei Diensten ist eine zusätzliche Implementierung normalerweise nicht nötig.

Wie geht man mit Single-Instance bei WPF-Anwendungen vor?

Bei WPF-Anwendungen überschreibt man die OnStartup-Methode in App.xaml.cs und prüft dort den Mutex. Alternativ bietet das NuGet-Paket Microsoft.Toolkit.Wpf.UI.Controls bzw. modernere Ansätze über IHostedService in .NET 6+ eine saubere Lösung.