Get window state of another process

How do I get the window state(maximized, minimized) of another process that's running?

I'd tried by using this:

Process[] procs = Process.GetProcesses();

        foreach (Process proc in procs)
        {

            if (proc.ProcessName == "notepad")
            {
                MessageBox.Show(proc.StartInfo.WindowStyle.ToString());

            }
        }

But if process is Maximized or Minimized,it ever returns Normal.

How to fix this?


You’ll need to use Win32 through P/Invoke for checking the state of another window. Here is some sample code:

static void Main(string[] args)
{
    Process[] procs = Process.GetProcesses();

    foreach (Process proc in procs)
    {
        if (proc.ProcessName == "notepad")
        {
            var placement = GetPlacement(proc.MainWindowHandle);
            MessageBox.Show(placement.showCmd.ToString());
        }
    }
}

private static WINDOWPLACEMENT GetPlacement(IntPtr hwnd)
{
    WINDOWPLACEMENT placement = new WINDOWPLACEMENT();
    placement.length = Marshal.SizeOf(placement);
    GetWindowPlacement(hwnd, ref placement);
    return placement;
}

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

[Serializable]
[StructLayout(LayoutKind.Sequential)]
internal struct WINDOWPLACEMENT
{
    public int length;
    public int flags;
    public ShowWindowCommands showCmd;
    public System.Drawing.Point ptMinPosition;
    public System.Drawing.Point ptMaxPosition;
    public System.Drawing.Rectangle rcNormalPosition;
}

internal enum ShowWindowCommands : int
{
    Hide = 0,
    Normal = 1,
    Minimized = 2,
    Maximized = 3,
}

Definition courtesy of pinvoke.net.


You're using proc.StartInfo, which is incorrect. It does not reflect the runtime window style of the target process. It is just startup info you can set and can then be passed on to the process when it starts up.

The C# signature is:

[DllImport("user32.dll", SetLastError=true)]
static extern int GetWindowLong(IntPtr hWnd, int nIndex);

You need to use p/invoke and call GetWindowLong(hWnd, GWL_STYLE), and pass proc.MainWindowHandle as the hWnd parameter.

You can check if the window is minimized/maximized by doing something like:

int style = GetWindowLong(proc.MainWindowHandle,  GWL_STYLE);
if((style & WS_MAXIMIZE) == WS_MAXIMIZE) 
{
   //It's maximized
} 
else if((style & WS_MINIMIZE) == WS_MINIMIZE) 
{
  //It's minimized
}

NOTE: The values for the flags (WS_MINIMIZE, etc), can be found in this page: http://www.pinvoke.net/default.aspx/user32.getwindowlong

Thanks to Kakashi for pointing our the error in testing the result.


In Windows PowerShell you can do this by following code:

Add-Type -AssemblyName UIAutomationClient
$prList = Get-Process -Name "<ProcessNamesWhichHaveWindow>"
$prList | % {
    $ae = [System.Windows.Automation.AutomationElement]::FromHandle($_.MainWindowHandle)
    $wp = $ae.GetCurrentPattern([System.Windows.Automation.WindowPatternIdentifiers]::Pattern)
    echo "Window title: $($_.MainWindowTitle)"
    echo "Window visual state: $($wp.Current.WindowVisualState)"
}

Two Window States (maximized / minimized) can be gotten by calling WinAPI IsIconic() / IsZoomed() like this:

    [DllImport("user32.dll")]
    [return: MarshalAs(UnmanagedType.Bool)]
    public static extern bool IsIconic(IntPtr hWnd);

    [DllImport("user32.dll")]
    public static extern bool ShowWindowAsync(IntPtr hWnd, ShowWindowCommands cmdShow);

    if (IsIconic(_helpWindow.MainWindowHandle)) {
        ShowWindowAsync(_helpWindow.MainWindowHandle, ShowWindowCommands.SW_RESTORE);
    }

Definition of enum ShowWindowCommands and other functions were taken from www.PInvoke.net