如何判断进程是否具有图形界面?

时间:2010-09-24 09:20:28

标签: c# ui-automation

我正在使用自动化来测试应用程序,但有时我想通过批处理文件启动应用程序。当我运行“process.WaitForInputIdle(100)”时,我收到一个错误:

“WaitForInputIdle失败。这可能是因为该进程没有图形界面。”

如何判断流程是否具有图形界面?

4 个答案:

答案 0 :(得分:8)

Environment.UserInteractive。这将确定该过程是否具有接口,例如服务不是用户互动的。

您还可以查看Process.MainWindowHandle,它会告诉您是否有图形界面。

这两项检查的组合应涵盖所有可能性。

答案 1 :(得分:0)

您可以尝试捕获异常:

Process process = ...
try
{
    process.WaitForInputIdle(100);
}
catch (InvalidOperationException ex)
{
    // no graphical interface
}

答案 2 :(得分:0)

我按照这个想法思考,仍然很丑,但试图避免异常。

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;
    }
}

答案 3 :(得分:0)

除了MainWindowHandle检查之外,还可以枚举进程线程并检查其中是否有任何线程通过P / Invokes引用可见窗口。这似乎很好地抓住了第一次检查错过的任何窗口。

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);