How to close Discord programmatically?

Viewed 1179

I would like to close Discord programmatically, in a proper way (without calling Process.Kill()).

AFAIK the usual way to close a program elegantly is to check if there is a main window associated to the process (eg : Process.MainWindowHandle != IntPtr.Zero) and then call Process.CloseMainWindow(). It will send a close message to the main window.

It does not work with Discord as the main window might be already closed, with the program still running in background. The usual way to exit Discord is to right click on the task bar icon and choose "Quit Discord" not just closing the main window.

When Windows is shutting down, Discord close itself automatically. I don't think Windows simply kill all Discord processes so maybe there a way to do something similar to what Windows does ?

1 Answers

When Windows is shutting down, it sends a bunch of events to the application, including WM_ENDSESSION and WM_QUIT. Besides, the process is complicated and not easy to replicate. However, you can override message handler System.Windows.Forms.Control.WndProc to do something before letting the system processes the message.

If you want to exit an application programmatically, try to send those 2 messages to the process, using public static extern IntPtr PostMessage.

Example:

[DllImport("user32.dll")]
public static extern IntPtr PostMessage(IntPtr hWnd, uint Msg, IntPtr wParam, IntPtr lParam);

const uint WM_QUERYENDSESSION = 0x11
const uint ENDSESSION_CLOSEAPP = 0x1;

public static void SendMessageToProcess(string processName)
{
    Process[] processList = Process.GetProcesses();
    foreach (var p in processList)
    {
        if (p.ProcessName.Equals(processName))
        {
            IntPtr hWnd = p.MainWindowHandle;
            PostMessage(hWnd, WD_QUERYENDSESSION, true, ENDSESSION_CLOSEAPP);
        }
    }
}

[System.Security.Permissions.PermissionSet(System.Security.Permissions.SecurityAction.Demand, Name="FullTrust")]
protected override void WndProc(ref Message m) 
{
    switch (m.Msg)
    {
        case WM_QUERYENDSESSION:
            //Do something
    }
    base.WndProc(ref m);
}
Related