How can I tell if a process has a graphical interf

2019-02-16 17:38发布

I'm using automation to test an application, but sometimes I want to start the application via a batch file. When I run "process.WaitForInputIdle(100)" I get an error:

"WaitForInputIdle failed. This could be because the process does not have a graphical interface."

How can I tell if the process has a graphical interface or not?

4条回答
爷的心禁止访问
2楼-- · 2019-02-16 18:16

See Environment.UserInteractive. That will identify whether the process has an interface at all, e.g. services are not user interactive.

You could also look at Process.MainWindowHandle which will tell you whether there is a graphical interface.

A combination of these two checks should cover all the possibilities.

查看更多
霸刀☆藐视天下
3楼-- · 2019-02-16 18:20

As well as a MainWindowHandle check, one can enumerate the process threads and check if any of them reference a visible window via P/Invokes. This seems to do a good job catching any windows that the first check misses.

private Boolean isProcessWindowed(Process externalProcess)
{
    if (externalProcess.MainWindowHandle != IntPtr.Zero)
    {
        return true;
    }

    foreach (ProcessThread threadInfo in externalProcess.Threads)
    {
        IntPtr[] windows = GetWindowHandlesForThread(threadInfo.Id);

        if (windows != null)
        {
            foreach (IntPtr handle in windows)
            {
                if (IsWindowVisible(handle))
                {
                    return true;
                }
            }
        }
    }

    return false;
}

private IntPtr[] GetWindowHandlesForThread(int threadHandle)
{
    results.Clear();
    EnumWindows(WindowEnum, threadHandle);

    return results.ToArray();
}

private delegate int EnumWindowsProc(IntPtr hwnd, int lParam);

private List<IntPtr> results = new List<IntPtr>();

private int WindowEnum(IntPtr hWnd, int lParam)
{
    int processID = 0;
    int threadID = GetWindowThreadProcessId(hWnd, out processID);
    if (threadID == lParam)
    {
        results.Add(hWnd);
    }

    return 1;
}

[DllImport("user32.Dll")]
private static extern int EnumWindows(EnumWindowsProc x, int y);
[DllImport("user32.dll")]
public static extern int GetWindowThreadProcessId(IntPtr handle, out int processId);
[DllImport("user32.dll")]
static extern bool IsWindowVisible(IntPtr hWnd);
查看更多
SAY GOODBYE
4楼-- · 2019-02-16 18:23

You can simply try and catch the exception:

Process process = ...
try
{
    process.WaitForInputIdle(100);
}
catch (InvalidOperationException ex)
{
    // no graphical interface
}
查看更多
We Are One
5楼-- · 2019-02-16 18:26

I was think along the lines of this, Still ugly but trys to avoid exceptions.

Process process = ...

bool hasUI = false;

if (!process.HasExited)
{
    try
    {
        hasUI = process.MainWindowHandle != IntPtr.Zero;
    }
    catch (InvalidOperationException)
    {
        if (!process.HasExited)
            throw;
    }
}

if (!process.HasExited && hasUI)
{

    try
    {
        process.WaitForInputIdle(100);
    }
    catch (InvalidOperationException)
    {
        if (!process.HasExited)
            throw;
    }
}
查看更多
登录 后发表回答