【问题标题】:Clicking AutomationElement Dialogue Box单击 AutomationElement 对话框
【发布时间】:2019-03-31 07:25:16
【问题描述】:

我正在自动化安装程序,因为它没有(功能性)/silent 开关。它工作得很好,除了我遇到了一个似乎是路障的东西——一个可怕的对话框。 看起来像this

我尝试过的:

SendKey.Send/Wait(Enter/Escape)
PostMessage(proc.MainWindowHandle, WM_KEYDOWN, VK__RETURN, 0);

将密钥注入进程

injector.SimulateTap((int) centre.X + 150, (int) centre.Y + 75); 

触摸注入,不会在此特定窗口上注册,但所有其他窗口都可以正常工作。

Walking over the element as if it were just a normal element

我几乎不知所措,因为我非常希望手动按下此按钮(这也会打乱自动安装的其余部分)。 p>

我知道为什么找不到(或者我想是的);因为它是一个新的对话,我认为 enter 不起作用,因为它发送到错误的进程(对话框的父进程,安装程序)和我一无所知的触摸注入。

文档中没有谈到如何处理对话框(也都是 C++)。

通常,我会遍历元素以找到下一个控件以继续安装。有几个控件:

    string[] EGalaxTouchInstallSequence = {
        @"Next >",
        "I accept the terms of the license agreement",
        @"Next >",
        "None",
        null, //this is supposed to represent a dialogue popup
        "OK",
        "Support Multi-Monitor System",
        @"Next >",
        @"Next >",
        @"Next >",
        @"Next >",
        @"Next >"
    };

最初,我从窗口中获取所有句柄,如下所示:

    AutomationElement UIElement = AutomationElement.FromHandle(SetupWindow);

我遍历列表:

        foreach (string button in EGalaxTouchInstallSequence)
        {
            if (!FindAndClickElement(UIElement, button))
                goto error;
        }

FindAndClickElement:

    private bool FindAndClickElement(AutomationElement UIElement, string ElementName)
    {
        AutomationElement element = null;

        Condition ControlProperty = new PropertyCondition(AutomationElement.NameProperty, ElementName);

        AutomationElementCollection elements = UIElement.FindAll(TreeScope.Descendants, ControlProperty);

        foreach (AutomationElement e in elements)
        {
            if (e.Current.Name.Contains(ElementName))
            {
                Console.WriteLine("Match with: " + ElementName);
                element = e;
            }

        }
        //Click code is further down, irrelevant at this stage
     }

Element Exists:

private bool ElementExists(AutomationElement UIElement, string ElementName)
{
    Condition ControlProperty = new PropertyCondition(AutomationElement.NameProperty, ElementName);

    AutomationElementCollection elements = UIElement.FindAll(TreeScope.Descendants, ControlProperty);

    foreach (AutomationElement e in elements)
    {
        Console.WriteLine($"element name: {e.Current.Name}");
        if (e.Current.Name.Contains(ElementName))
        {
            return true;
        }
    }

    return false;
}

【问题讨论】:

  • 对话框是桌面的子级还是桌面的子级?我发现当我按类名查找窗口时,有时我会找到工具提示,因为它们是窗口。
  • 它似乎是 InstallShield 安装程序的子进程 - 我检查了安装进程的子进程,但它没有名称或任何内容,因此很难假设该子进程是否只是内部InstallShield 安装程序的窗口,或者如果它是对话框,但我不确定如何找到,因为它没有任何其他子项。
  • 所以在我们的 WPF 应用程序中,我做了这样的事情来防止自己找到工具提示。 FindAll("...").FirstOrDefault(a => a.FirstChild().ClassName != "ToolTip"); 这很慢,但我找到了最好的解决方案。
  • 我可以尝试,但无论我如何操作(输入、触摸、退出等),窗口都要求我通过对话。我会看看我是否可以尝试找到一个工具提示(我不认为它是一个工具提示,但没有其他关闭的控件)。

标签: c# .net windows ui-automation


【解决方案1】:

在你去获取元素之前,我会检查一下那里有什么。我使用这样的方法来获取所有内容。

  /// <summary>
  ///    Returns all children elements of an automation element.
  /// </summary>
  /// <param name="automationElement"></param>
  /// <returns></returns>
  public static List<AutomationElement> AllChildren(AutomationElement automationElement)
  {
     if (automationElement == null) throw new ArgumentNullException(nameof(automationElement));

     AutomationElement firstChild = TreeWalker.RawViewWalker.GetFirstChild(automationElement);
     if (firstChild == null)
        return new List<AutomationElement>();

     List<AutomationElement> children = new List<AutomationElement> { firstChild };

     AutomationElement sibling;
     int childIndex = 0;
     while ((sibling = TreeWalker.RawViewWalker.GetNextSibling(children[childIndex])) != null)
     {
        children.Add(sibling);
        childIndex++;
     }

     return children;
  }

此外,正如我在评论中所说,请确保您不会通过使用类似 FindAll("...").FirstOrDefault(a =&gt; a.FirstChild().ClassName != "ToolTip"); 的内容意外找到工具提示。工具提示通常不会显示,因为应用程序单击事物的速度非常快,因此它的位置将具有 (-1, -1)。

【讨论】:

  • 这看起来很有趣。我会将其应用于哪个元素?主窗口?我将把它应用到每个“Next >”按钮上,看看它会吐出什么,谢谢。
  • 我会尝试主窗口,因为通常模式对话框由产生它们的窗口拥有,但这取决于开发人员声称对它们的所有权。我们的应用程序有一些桌面拥有的对话框(因为我们没有声明对它们的所有权),而我们的应用程序有一些。
  • 谢谢。我会试一试,不过你可能要到星期一才能得到回复:)
  • 不幸的是,它似乎没有任何孩子。我在AutomationElement UIElement = AutomationElement.FromHandle(SetupWindow); 以及何时调用FindAndClick 时对您的函数结果运行了foreach。
  • 我建议的另一件事是重试查找您正在寻找的元素。我专门为此目的创建了一个库github.com/maxinfet/Mulligan。它封装了来自 FlaUI 和 TestStack.White 的重试逻辑。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-01-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-01-13
  • 2012-01-08
相关资源
最近更新 更多