Cel
Cel

Reputation: 6659

Detect if external process is interactive and has any visible UI

I cannot seem to find a way to determine whether a Process has a user interface e.g. a window, which is visible to the user?

I would like to differentiate between say Notepad and conhost

Upvotes: 1

Views: 2547

Answers (3)

E235
E235

Reputation: 13440

Following @David Heffernan, this is what I did:

HWND FindTopWindow(DWORD pid)
{
    std::pair<HWND, DWORD> params = { 0, pid };

    // Enumerate the windows using a lambda to process each window
    BOOL bResult = EnumWindows([](HWND hwnd, LPARAM lParam) -> BOOL
    {
        auto pParams = (std::pair<HWND, DWORD>*)(lParam);

        DWORD processId;
        if (GetWindowThreadProcessId(hwnd, &processId) && processId == pParams->second)
        {
            if (IsWindowVisible(hwnd)) {
                // Stop enumerating
                SetLastError(-1);
                pParams->first = hwnd;
                return FALSE;
            }

            return TRUE;
        }

        // Continue enumerating
        return TRUE;
    }, (LPARAM)&params);

    if (!bResult && GetLastError() == -1 && params.first)
    {
        return params.first;
    }

    return 0;
}

Upvotes: 1

Michel de Nijs
Michel de Nijs

Reputation: 406

The MSDN article about System.Diagnostics.Process.MainWindowHandle states the following

If you have just started a process and want to use its main window handle, consider using the WaitForInputIdle method to allow the process to finish starting, ensuring that the main window handle has been created. Otherwise, an exception will be thrown.

What they are implying is that the Window might take several seconds to render after you've made the call for the MainWindowHandle, returning IntPtr.Zero even though you can clearly see a Window is shown.

See https://msdn.microsoft.com/en-us/library/system.diagnostics.process.mainwindowhandle(v=vs.110).aspx for reference

Upvotes: 2

David Heffernan
David Heffernan

Reputation: 612993

  1. Find out the process ID from your Process instance.
  2. Enumerate the top-level windows with EnumWindows.
  3. Call GetWindowThreadProcessId and see if it matches the target PID.
  4. Call IsWindowVisible and/or IsIconic to test if that window is visible to the user.

Upvotes: 2

Related Questions