单击AutomationElement对话框

时间:2018-10-26 13:54:54

标签: c# .net windows ui-automation

我正在自动执行安装程序,因为它没有(功能性)/静音开关。它工作得很好,除非我遇到了似乎是一个障碍的地方-一个可怕的对话框。 看起来像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

我很茫然,因为我非常想不必手动 按下此按钮(这也会弄乱自动安装的其余部分)。

我知道为什么找不到(或者我认为如此);因为这是一次新的对话,所以我认为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;
}

1 个答案:

答案 0 :(得分: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 => a.FirstChild().ClassName != "ToolTip");之类的内容来找到工具提示。由于应用程序单击内容的速度很快,因此通常不会显示工具提示,因此其位置的位置为(-1,-1)。