Restore a minimized window of another application

... Apparently you cannot trust the information a Process gives you.

Process.MainWindowHandle returns the window handle of the first window created by the application, which is USUALLY that app's main top-level window. However, in my case, a call to FindWindow() shows that the handle of the actual window I want to restore is not what MainWindowHandle is pointing to. It appears that the window handle from the Process, in this case, is that of the splash screen shown as the program loads the main form.

If I call ShowWindow on the handle that FindWindow returned, it works perfectly.

What's even more unusual is that when the window's open, the call to SetForegroundWindow(), when given the process's MainWindowHandle (which should be invalid as that window has closed), works fine. So obviously that handle has SOME validity, just not when the window's minimized.

In summary, if you find yourself in my predicament, call FindWindow, passing it the known name of your external app's main window, to get the handle you need.


Working code using FindWindow method:

[DllImport("user32.dll")]
public static extern IntPtr FindWindow(string className, string windowTitle);

[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool ShowWindow(IntPtr hWnd, ShowWindowEnum flags);

[DllImport("user32.dll")]
private static extern int SetForegroundWindow(IntPtr hwnd);

[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool GetWindowPlacement(IntPtr hWnd, ref Windowplacement lpwndpl);

private enum ShowWindowEnum
{
    Hide = 0,
    ShowNormal = 1, ShowMinimized = 2, ShowMaximized = 3,
    Maximize = 3, ShowNormalNoActivate = 4, Show = 5,
    Minimize = 6, ShowMinNoActivate = 7, ShowNoActivate = 8,
    Restore = 9, ShowDefault = 10, ForceMinimized = 11
};

private struct Windowplacement
{
    public int length;
    public int flags;
    public int showCmd;
    public System.Drawing.Point ptMinPosition;
    public System.Drawing.Point ptMaxPosition;
    public System.Drawing.Rectangle rcNormalPosition;
}

private void BringWindowToFront()
{
    IntPtr wdwIntPtr = FindWindow(null, "Put_your_window_title_here");

    //get the hWnd of the process
    Windowplacement placement = new Windowplacement();
    GetWindowPlacement(wdwIntPtr, ref placement);

    // Check if window is minimized
    if (placement.showCmd == 2)
    {
        //the window is hidden so we restore it
        ShowWindow(wdwIntPtr, ShowWindowEnum.Restore);
    }

    //set user's focus to the window
    SetForegroundWindow(wdwIntPtr);
}

You can use it by calling BringWindowToFront().

I always have one instance of the application running so if you can have several open instances simultaneously you might want to slightly change the logic.