Fremde Programme beenden in C#


Vor einigen Tagen trat ein Kollege mit einem Anliegen an mich heran: Er wollte mit seinem Programm eine andere Anwendung schließen. Als langjähriger C++ Entwickler hatte ich sofort eine Idee, wie das funktioniert. Mit Windows Messages. Sendet man ein WM_CLOSE an eine Anwendung, beendet sie ordnungsgemäß. Allerdings ist der Versand von solchen Nachrichten im .NET Framework von Haus aus nicht vorgesehen. Man muss sich der user32.dll bedienen und die benötigte Funktion importieren.

[DllImport("user32.dll")]

public static extern IntPtr SendMessage(IntPtr hWnd, uint Msg, IntPtr wParam, IntPtr lParam);

Zusätzlich ist es vor Vorteil, eine Konstante zu deklarieren, die dem Wert einer WM_CLOSE Nachricht entspricht. Da kann ein Blick in die Windows-API Dokumentation helfen. WM_CLOSE entspricht 0x0010.

const uint WM_CLOSE = 0x0010;

Bevor die Nachricht gesendet werden kann, muss die Frage beantwortet werden: Wohin? Benötigt wird ein Handle auf die zu schließende Anwendung. Es gibt verschiedene Wege an ein Handle zu gelangen, unter anderem über den Namen des Prozesses. Das ist dann eine Aufgabe für die GetProcessesByName-Methode.

IntPtr GetTargetHandle(string processName)

{

    IntPtr hwnd = IntPtr.Zero;


    Process[] procs = Process.GetProcessesByName(processName);

    if (procs.Length != 0)

    {

        Debug.WriteLine("Prozess gefunden: " + procs[0].ProcessName);

        hwnd = procs[0].MainWindowHandle;

    }

    else

    {

        Debug.WriteLine(processName + " nicht gefunden.");

        return hwnd;

    }

    return hwnd;

}

Nachdem das Handle erfolgreich ermittelt wurde, kann die Nachricht gesendet werden. Weil mit einem WM_CLOSE keine weiteren Informationen übertragen werden müssen, erhält die SendMessage-Methode für die Parameter wParam und lParam ein IntPtr.Zero (Null-Pointer). Das ist alles!

IntPtr targetHandle = GetTargetHandle(processName);


if (this.targetHandle != IntPtr.Zero)

{

     SendMessage(targetHandle, WM_CLOSE, IntPtr.Zero, IntPtr.Zero); 

}

Bei meinen Nachforschungen zu dem Thema fand ich anschließend heraus, dass fremde Programm durchaus auch mit .NET Bordmitteln geschlossen werden können. Ruft man für einen Prozess CloseMainWindow auf, endet eine Anwendung ebenfalls. Sollte das nicht ausreichten, hilft eventuell ein Aufruf von Kill beim gesuchten Prozess. Eine Liste aller Prozesse liefert die Methode GetProcesses.

Process[] processes = Process.GetProcesses();


foreach (Process process in processes)

{

    if (process.ProcessName == processName)

    {

        process.CloseMainWindow();

        // process.Kill(); // Alternativ, beendet einen Prozess 

        break;

     }

}


Geschrieben am: 15.07.2020
Technologien: Window, C#, .Net