C# 自动化用户界面-自定义控件赢得';我没有出现
我有一个自动化用户界面的问题。 我有一个可以工作的代码,但很难调试-所以我创建了一个应该更舒适的代码,但在一个情况下,它不会工作-这种情况下是一个自定义控件 我不明白为什么一个代码能工作,而另一个不能! 我尝试了很多方法并在网上搜索(很多类似的东西,但对我来说还不够好) 这是有效的代码:C# 自动化用户界面-自定义控件赢得';我没有出现,c#,automation,C#,Automation,我有一个自动化用户界面的问题。 我有一个可以工作的代码,但很难调试-所以我创建了一个应该更舒适的代码,但在一个情况下,它不会工作-这种情况下是一个自定义控件 我不明白为什么一个代码能工作,而另一个不能! 我尝试了很多方法并在网上搜索(很多类似的东西,但对我来说还不够好) 这是有效的代码: class ElementUtils { public ElementUtils() { } public AutomationElement FindObject
class ElementUtils
{
public ElementUtils()
{
}
public AutomationElement FindObjectFullPath(string parent, string childElements, string controlType)
{
string[] strElements = null;
if (!string.IsNullOrEmpty(childElements))
{
childElements = childElements.Trim();
strElements = childElements.Split(new string[] { "[", "]" }, StringSplitOptions.RemoveEmptyEntries);
if (string.IsNullOrEmpty(parent) && !(childElements.StartsWith("[") && childElements.EndsWith("]")))
throw new Exception("parent element and child elements are all empty. this input cannot be processed!");
if (string.IsNullOrEmpty(parent))
parent = strElements[0];
}
AutomationElement e = null;
AutomationElementCollection desktop = GetDesktopElements();
e = FindElement(desktop, parent);
if (e == null)
{
return null;
}
AutomationElement ae = e;
if (strElements != null) // ignore parent if you have full path element format
ae = LocateElement(strElements, e, controlType);
if (ae != null)
{
string fullPath = BuildElementFullNameForTest(ae);
return ae;
}
return null;
}
private AutomationElement LocateElement(string[] elements, AutomationElement ae, string controlType)
{
AutomationElement e = ae;
List<AutomationElement> eList = new List<AutomationElement>();
List<AutomationElement> newElemList = new List<AutomationElement>();
eList.Add(e);
for (int i = 0; i < elements.Length; i++)
{
if (elements[i] == "null")
continue;
if (elements[i] == "empty")
elements[i] = "";
newElemList.Clear();
newElemList.AddRange(eList);
eList.Clear();
foreach (AutomationElement ee in newElemList)
{
AutomationElementCollection c = GetObjectElements(ee);
bool exactMatch = false;
if (elements[i].StartsWith("#") && elements[i].EndsWith("#"))
{
elements[i] = elements[i].Substring(1, elements[i].Length - 2);
exactMatch = true;
}
if (i == elements.Length - 1 && !controlType.Equals("IGNORE") && !controlType.Equals(""))
{
eList.AddRange(FindAllSubElements(c, elements[i], StringToControlType(controlType), exactMatch));
}
else
{
eList.AddRange(FindAllSubElements(c, elements[i], null, exactMatch));
}
}
}
if (eList.Count == 0)
return null;
return eList[0];
}
private List<AutomationElement> FindAllSubElements(AutomationElementCollection c, string ae, ControlType controlType, bool exactMatch)
{
List<AutomationElement> eList = new List<AutomationElement>();
bool found = false;
for (int i = 0; i < c.Count; i++)
{
// name should be exactly as expected element name
if (exactMatch)
{
if (c[i].Current.Name.Equals(ae))
found = true;
}
else if (c[i].Current.Name.Contains(ae)) // name should be contained in expected element name
{
found = true;
}
if (found)
{
found = false;
if (controlType != null)
{
if (c[i].Current.ControlType.CompareTo(controlType) == 0)
{
eList.Add(c[i]);
}
}
else
{
eList.Add(c[i]);
}
}
}
return eList;
}
public AutomationElementCollection GetDesktopElements()
{
return AutomationElement.RootElement.FindAll(TreeScope.Children, System.Windows.Automation.Condition.TrueCondition);
}
public AutomationElementCollection GetObjectElements(AutomationElement e)
{
return e.FindAll(TreeScope.Subtree, System.Windows.Automation.Condition.TrueCondition);
}
private AutomationElement FindElement(AutomationElementCollection c, string name)
{
for (int i = 0; i < c.Count; i++)
{
if (c[i].Current.Name.Contains(name))
{
return c[i];
}
}
return null;
}
private AutomationElement FindElement(AutomationElementCollection c, string name, ControlType controlType)
{
for (int i = 0; i < c.Count; i++)
{
if (c[i].Current.Name.Contains(name) && c[i].Current.ControlType.CompareTo(controlType) == 0)
return c[i];
}
return null;
}
private AutomationElement FindElement(List<AutomationElement> elements, string name)
{
foreach (AutomationElement e in elements)
{
if (e.Current.Name.Contains(name))
return e;
}
return null;
}
private string BuildElementFullNameForTest(AutomationElement element)
{
TreeWalker walker = TreeWalker.ControlViewWalker;
AutomationElement elementParent;
AutomationElement node = element;
if (element == null)
{
return null;
}
string elementFullName = element.Current.Name + "]";
do
{
elementParent = walker.GetParent(node);
if (elementParent == AutomationElement.RootElement)
break;
if (!elementParent.Current.Name.Equals(""))
elementFullName = elementParent.Current.Name + "][" + elementFullName;
node = elementParent;
}
while (true);
return "[" + elementFullName;
}
private void WalkAllElements(AutomationElement rootElement, List<AutomationElement> collection)
{
TreeWalker walker = TreeWalker.ControlViewWalker;
AutomationElement e = walker.GetFirstChild(rootElement);
while (e != null)
{
collection.Add(e);
WalkAllElements(e, collection);
e = walker.GetNextSibling(e);
}
}
private ControlType StringToControlType(string controlType)
{
switch (controlType)
{
case "Button":
return ControlType.Button;
case "Calendar":
return ControlType.Calendar;
case "CheckBox":
return ControlType.CheckBox;
case "ComboBox":
return ControlType.ComboBox;
case "DataGrid":
return ControlType.DataGrid;
case "DataItem":
return ControlType.DataItem;
case "Document":
return ControlType.Document;
case "Edit":
return ControlType.Edit;
case "Group":
return ControlType.Group;
case "Header":
return ControlType.Header;
case "HeaderItem":
return ControlType.HeaderItem;
case "Hyperlink":
return ControlType.Hyperlink;
case "Image":
return ControlType.Image;
case "List":
return ControlType.List;
case "ListItem":
return ControlType.ListItem;
case "Menu":
return ControlType.Menu;
case "MenuBar":
return ControlType.MenuBar;
case "MenuItem":
return ControlType.MenuItem;
case "Pane":
return ControlType.Pane;
case "ProgressBar":
return ControlType.ProgressBar;
case "RadioButton":
return ControlType.RadioButton;
case "ScrollBar":
return ControlType.ScrollBar;
case "Separator":
return ControlType.Separator;
case "Slider":
return ControlType.Slider;
case "Spinner":
return ControlType.Spinner;
case "SplitButton":
return ControlType.SplitButton;
case "StatusBar":
return ControlType.StatusBar;
case "Tab":
return ControlType.Tab;
case "TabItem":
return ControlType.TabItem;
case "Table":
return ControlType.Table;
case "Text":
return ControlType.Text;
case "Thumb":
return ControlType.Thumb;
case "TitleBar":
return ControlType.TitleBar;
case "ToolBar":
return ControlType.ToolBar;
case "ToolTip":
return ControlType.ToolTip;
case "Tree":
return ControlType.Tree;
case "TreeItem":
return ControlType.TreeItem;
case "Window":
return ControlType.Window;
default:
return null;
}
}
}
而在第二代码段中,元素树的填充代码为
public ObjectFinderElement(AutomationElement current, TestLog testlog)
{
ofl = testlog;
this.current = current;
AutomationElementCollection childrenTemp = current.FindAll(TreeScope.Children, System.Windows.Automation.Condition.TrueCondition);
children.Capacity = childrenTemp.Count;
foreach (AutomationElement child in childrenTemp)
children.Add(new ObjectFinderElement(child, ofl));
}
所以我猜是树镜。但是,即使(出于测试目的)我将范围更改为子树(让列表变得疯狂,并且包含多个元素),丢失的元素仍然不会出现
我将在下面发布我收到的树(当然,treescope=Children):
我想这是一本很值得一读的书,但是如果能帮上忙,我将不胜感激
更新:
我发现了另一个提示——似乎为了找到所有元素,我需要使用“AutomationElement.RootElement.FindAll(TreeScope.Subtree,System.Windows.Automation.Condition.TrueCondition);”
所以我不能像树一样组织它!这很麻烦
另外,我很难将文本作为代码发布…我已经解决了这个问题。我不知道该怎么做,我打算暂时放弃它,所以我从零开始快速重写了一次。3-4分钟后,它就可以工作了 以下是相关人员的代码
using AutomationUtils;
using System;
using System.Collections.Generic;
using System.Threading;
using System.Windows.Automation;
namespace GenericUIAutomation
{
class ElementTree
{
private AutomationElement current;
private List<ElementTree> children = new List<ElementTree>();
private List<String> ancestorNames = new List<String>();
private static TestLog ofl;
public ElementTree(TestLog testlog)
{
ofl = testlog;
this.current = AutomationElement.RootElement;
//This is the root element, no ancestors.
ancestorNames = null;
AutomationElementCollection childrenTemp = current.FindAll(TreeScope.Children, System.Windows.Automation.Condition.TrueCondition);
children.Capacity = childrenTemp.Count;
List<String> childrenAncestors = new List<String>();
childrenAncestors.Add(this.current.Current.Name);
foreach (AutomationElement child in childrenTemp)
children.Add(new ElementTree(child, childrenAncestors));
childrenTemp = null;
}
public ElementTree(AutomationElement current, List<String> ancestorList)
{
this.current = current;
this.ancestorNames = ancestorList;
AutomationElementCollection childrenTemp = current.FindAll(TreeScope.Children, System.Windows.Automation.Condition.TrueCondition);
children.Capacity = childrenTemp.Count;
List<String> childrenAncestors = new List<String>();
childrenAncestors.AddRange(ancestorList);
childrenAncestors.Add(this.current.Current.Name);
foreach (AutomationElement child in childrenTemp)
children.Add(new ElementTree(child, childrenAncestors));
childrenTemp = null;
}
public ElementTree FindInTree(String name, ControlType controlType, String[] ancestorList)
{
String ct = "IGNORE";
if (controlType != null)
ct = controlType.LocalizedControlType.ToString();
ofl.AddLine("Scanning for \"" + name + "\" - " + " Control Type: " + ct);
ElementTree res = FindInTreeIMP(name, controlType, ancestorList);
if (res != null)
ofl.AddLine("Success! Found element \"" + res.GetName() + "\" - " + res.GetAutomationElement().Current.ControlType.LocalizedControlType);
else
ofl.AddLine("Error! No matching element found.");
return res;
}
public ElementTree FindInTreeIMP(String name, ControlType controlType, String[] ancestorList)
{
ofl.AddLine("Scanning element \"" + current.Current.Name + "\" - " + current.Current.ControlType.LocalizedControlType);
Boolean found = CompareElements(name, controlType, ancestorList);
if (found)
return this;
foreach (ElementTree child in children)
{
ElementTree res = child.FindInTreeIMP(name, controlType, ancestorList);
if (res != null)
return res;
}
return null;
}
private Boolean CompareElements(String name, ControlType controlType, String[] ancestorList)
{
Boolean found = false;
//name should be contained in expected element name
if (this.current.Current.Name.Contains(name))
{
PrintToLog("Name match found");
found = true;
}
//Test for control type, if needed
if (found == true && controlType != null)
{
PrintToLog("Control Type match found");
if (this.current.Current.ControlType.CompareTo(controlType) != 0)
found = false;
}
if (found == true && this.ancestorNames.Count >= ancestorList.Length)
{
PrintToLog("Searching for Ancestors");
found = CheckAncestors(ancestorList);
}
else
found = false;
return found;
}
private Boolean CheckAncestors(String[] ancestorList)
{
Boolean found = false;
foreach (String ancestorName in ancestorList)
{
PrintToLog("Scanning for ancestor " + ancestorName);
foreach (String ancestorListElement in ancestorList)
if (ancestorListElement.Contains(ancestorName))
{
PrintToLog("Found ancestor " + ancestorListElement);
found = true;
break;
}
if (found != true)
return found;
else
continue;
}
return found;
}
public String PrintTree()
{
return "\n" + PrintTree("");
}
public String PrintTree(String preText)
{
String self = preText + GetExtendedInfo();
foreach (ElementTree child in children)
self += "\n" + preText + child.PrintTree(preText + " |");
return self;
}
public AutomationElement GetAutomationElement()
{
return current;
}
public String GetName()
{
return current.Current.Name;
}
public String GetExtendedInfo()
{
int childrenCount = 0;
int ancestorsCount = 0;
String name = current.Current.Name;
String controlType = current.Current.ControlType.LocalizedControlType;
if (children != null)
childrenCount = children.Count;
if (ancestorNames != null)
ancestorsCount = ancestorNames.Count;
return "\"" + name + "\" - " + controlType + " - " + childrenCount + " Children" + " - " + ancestorsCount + " Ancestors";
}
public void PrintToLog(String text)
{
ofl.AddLine(text);
}
}
}
使用自动化工具;
使用制度;
使用System.Collections.Generic;
使用系统线程;
使用System.Windows.Automation;
命名空间通用UIAutomation
{
类元素树
{
专用自动元件电流;
私有列表子项=新列表();
私有列表ancestorNames=新列表();
私有静态测试日志;
公共元素树(TestLog TestLog)
{
ofl=测试日志;
this.current=AutomationElement.RootElement;
//这是根元素,没有祖先。
ancestorNames=null;
AutomationElementCollection childrenTemp=current.FindAll(TreeScope.Children,System.Windows.Automation.Condition.TrueCondition);
children.Capacity=childrenTemp.Count;
List childrenAncestors=新列表();
添加(this.current.current.Name);
foreach(childrenTemp中的AutomationElement子级)
添加(新元素树(child,childrenAncestors));
childrenTemp=null;
}
公共元素树(AutomationElement当前、列表和存储列表)
{
这个电流=电流;
this.antestornames=antestorlist;
AutomationElementCollection childrenTemp=current.FindAll(TreeScope.Children,System.Windows.Automation.Condition.TrueCondition);
children.Capacity=childrenTemp.Count;
List childrenAncestors=新列表();
childrenAncestors.AddRange(ancestorList);
添加(this.current.current.Name);
foreach(childrenTemp中的AutomationElement子级)
添加(新元素树(child,childrenAncestors));
childrenTemp=null;
}
公共元素树FindInTree(字符串名称、控制类型ControlType、字符串[]和存储列表)
{
字符串ct=“忽略”;
if(controlType!=null)
ct=controlType.LocalizedControlType.ToString();
ofl.AddLine(“扫描\”+“名称+”\“-“+”控制类型:“+ct”);
ElementTree res=FindInTreeIMP(名称、控制类型、存储列表);
如果(res!=null)
ofl.AddLine(“成功!找到元素\”“+res.GetName()+“\”-“+res.GetAutomationElement().Current.ControlType.LocalizedControlType”);
其他的
AddLine(“错误!找不到匹配的元素。”);
返回res;
}
公共元素树FindInTreeIMP(字符串名称、控制类型、控制类型、字符串[]和存储列表)
{
ofl.AddLine(“扫描元素\”“+current.current.Name+“\”-“+current.current.ControlType.LocalizedControlType”);
Boolean found=比较元素(名称、控制类型、取消存储列表);
如果(找到)
归还这个;
foreach(子元素中的元素树子元素)
{
ElementTree res=child.FindInTreeIMP(名称、控制类型、取消存储列表);
如果(res!=null)
返回res;
}
返回null;
}
私有布尔比较元素(字符串名称、控制类型、控制类型、字符串[]和存储列表)
{
布尔值=false;
//名称应包含在预期的元素名称中
if(this.current.current.Name.Contains(Name))
{
PrintToLog(“找到名称匹配”);
发现=真;
}
//如果需要,测试控制类型
if(find==true&&controlType!=null)
{
PrintToLog(“找到控件类型匹配”);
if(this.current.current.ControlType.CompareTo(ControlType)!=0)
发现=错误;
}
if(find==true&&this.antestornames.Count>=antestorlist.Length)
{
PrintToLog(“寻找祖先”);
发现=检查祖先(取消存储列表);
}
其他的
发现=错误;
发现退货;
}
私有布尔校验祖先(字符串[]ancestorList)
{
布尔值=false;
foreach(ancestorList中的字符串ancestorName)
{
PrintToLog(“扫描祖先”+ancestorName);
foreach(ancestorList中的字符串ancestorListElement)
if(ancestorListElement.Contains(ancestorName))
{
PrintToLog(“发现的祖先”+ancestorListElement);
发现=真;
打破
}
如果(找到!=真)
发现退货;
其他的
继续;
}
发现退货;
}
公共字符串PrintTree()
{
返回“\n”+打印树(“”);
}
普布利
public ObjectFinderElement(AutomationElement current, TestLog testlog)
{
ofl = testlog;
this.current = current;
AutomationElementCollection childrenTemp = current.FindAll(TreeScope.Children, System.Windows.Automation.Condition.TrueCondition);
children.Capacity = childrenTemp.Count;
foreach (AutomationElement child in childrenTemp)
children.Add(new ObjectFinderElement(child, ofl));
}
2/10/2014 11:55:55 AM -
Log for object path [Folder List][Contacts]
2/10/2014 11:55:55 AM -
"Inbox - test320@****.com - Microsoft Outlook" - window - 11 Children
|"Frame Splitter" - pane - 0 Children
|"Frame Splitter" - pane - 0 Children
|"MsoDockTop" - pane - 1 Children
| |"Ribbon" - pane - 1 Children
| | |"Ribbon" - pane - 1 Children
| | | |"" - pane - 1 Children
| | | | |"" - pane - 0 Children
|"MsoDockBottom" - pane - 1 Children
| |"Status Bar" - pane - 1 Children
| | |"Status Bar" - pane - 1 Children
| | | |"" - pane - 1 Children
| | | | |"" - pane - 0 Children
|"" - pane - 0 Children
|"FolderBar" - pane - 1 Children
| |"NUIDocumentWindow" - pane - 1 Children
| | |"" - pane - 1 Children
| | | |"" - pane - 1 Children
| | | | |"" - pane - 0 Children
|"NUIDocumentWindow" - pane - 1 Children
| |"" - pane - 0 Children
|"NUIDocumentWindow" - pane - 1 Children
| |"" - pane - 0 Children
|"" - pane - 2 Children
| |"" - pane - 1 Children
| | |"" - pane - 13 Children
| | | |"DAL=on" - tool bar - 0 Children
| | | |"" - text - 0 Children
| | | |"TestAppointment" - pane - 0 Children
| | | |"" - pane - 0 Children
| | | |"" - pane - 0 Children
| | | |"Required: " - pane - 0 Children
| | | |"" - pane - 0 Children
| | | |"When:" - pane - 0 Children
| | | |"Saturday, June 04, 2016 8:00 AM-8:30 AM" - pane - 0 Children
| | | |"Location:" - pane - 0 Children
| | | |"None" - pane - 0 Children
| | | |"" - pane - 2 Children
| | | | |"Vertical" - pane - 1 Children
| | | | | |"" - pane - 0 Children
| | | | |"Day View" - pane - 0 Children
| | | |"" - pane - 1 Children
| | | | |"" - pane - 2 Children
| | | | | |"Message" - pane - 0 Children
| | | | | |"Vertical" - pane - 1 Children
| | | | | | |"" - pane - 0 Children
| |"Microsoft Outlook Social Connector" - pane - 2 Children
| | |"" - pane - 0 Children
| | |"Click to expand the People Pane" - button - 0 Children
|"Table View" - pane - 1 Children
| |"Vertical" - pane - 1 Children
| | |"" - pane - 0 Children
|"Inbox - test320@****.com - Microsoft Outlook" - title bar - 4 Children
| |"System Menu Bar" - menu bar - 1 Children
| | |"System" - menu item - 0 Children
| |"Minimize" - button - 0 Children
| |"Restore" - button - 0 Children
| |"Close" - button - 0 Children
using AutomationUtils;
using System;
using System.Collections.Generic;
using System.Threading;
using System.Windows.Automation;
namespace GenericUIAutomation
{
class ElementTree
{
private AutomationElement current;
private List<ElementTree> children = new List<ElementTree>();
private List<String> ancestorNames = new List<String>();
private static TestLog ofl;
public ElementTree(TestLog testlog)
{
ofl = testlog;
this.current = AutomationElement.RootElement;
//This is the root element, no ancestors.
ancestorNames = null;
AutomationElementCollection childrenTemp = current.FindAll(TreeScope.Children, System.Windows.Automation.Condition.TrueCondition);
children.Capacity = childrenTemp.Count;
List<String> childrenAncestors = new List<String>();
childrenAncestors.Add(this.current.Current.Name);
foreach (AutomationElement child in childrenTemp)
children.Add(new ElementTree(child, childrenAncestors));
childrenTemp = null;
}
public ElementTree(AutomationElement current, List<String> ancestorList)
{
this.current = current;
this.ancestorNames = ancestorList;
AutomationElementCollection childrenTemp = current.FindAll(TreeScope.Children, System.Windows.Automation.Condition.TrueCondition);
children.Capacity = childrenTemp.Count;
List<String> childrenAncestors = new List<String>();
childrenAncestors.AddRange(ancestorList);
childrenAncestors.Add(this.current.Current.Name);
foreach (AutomationElement child in childrenTemp)
children.Add(new ElementTree(child, childrenAncestors));
childrenTemp = null;
}
public ElementTree FindInTree(String name, ControlType controlType, String[] ancestorList)
{
String ct = "IGNORE";
if (controlType != null)
ct = controlType.LocalizedControlType.ToString();
ofl.AddLine("Scanning for \"" + name + "\" - " + " Control Type: " + ct);
ElementTree res = FindInTreeIMP(name, controlType, ancestorList);
if (res != null)
ofl.AddLine("Success! Found element \"" + res.GetName() + "\" - " + res.GetAutomationElement().Current.ControlType.LocalizedControlType);
else
ofl.AddLine("Error! No matching element found.");
return res;
}
public ElementTree FindInTreeIMP(String name, ControlType controlType, String[] ancestorList)
{
ofl.AddLine("Scanning element \"" + current.Current.Name + "\" - " + current.Current.ControlType.LocalizedControlType);
Boolean found = CompareElements(name, controlType, ancestorList);
if (found)
return this;
foreach (ElementTree child in children)
{
ElementTree res = child.FindInTreeIMP(name, controlType, ancestorList);
if (res != null)
return res;
}
return null;
}
private Boolean CompareElements(String name, ControlType controlType, String[] ancestorList)
{
Boolean found = false;
//name should be contained in expected element name
if (this.current.Current.Name.Contains(name))
{
PrintToLog("Name match found");
found = true;
}
//Test for control type, if needed
if (found == true && controlType != null)
{
PrintToLog("Control Type match found");
if (this.current.Current.ControlType.CompareTo(controlType) != 0)
found = false;
}
if (found == true && this.ancestorNames.Count >= ancestorList.Length)
{
PrintToLog("Searching for Ancestors");
found = CheckAncestors(ancestorList);
}
else
found = false;
return found;
}
private Boolean CheckAncestors(String[] ancestorList)
{
Boolean found = false;
foreach (String ancestorName in ancestorList)
{
PrintToLog("Scanning for ancestor " + ancestorName);
foreach (String ancestorListElement in ancestorList)
if (ancestorListElement.Contains(ancestorName))
{
PrintToLog("Found ancestor " + ancestorListElement);
found = true;
break;
}
if (found != true)
return found;
else
continue;
}
return found;
}
public String PrintTree()
{
return "\n" + PrintTree("");
}
public String PrintTree(String preText)
{
String self = preText + GetExtendedInfo();
foreach (ElementTree child in children)
self += "\n" + preText + child.PrintTree(preText + " |");
return self;
}
public AutomationElement GetAutomationElement()
{
return current;
}
public String GetName()
{
return current.Current.Name;
}
public String GetExtendedInfo()
{
int childrenCount = 0;
int ancestorsCount = 0;
String name = current.Current.Name;
String controlType = current.Current.ControlType.LocalizedControlType;
if (children != null)
childrenCount = children.Count;
if (ancestorNames != null)
ancestorsCount = ancestorNames.Count;
return "\"" + name + "\" - " + controlType + " - " + childrenCount + " Children" + " - " + ancestorsCount + " Ancestors";
}
public void PrintToLog(String text)
{
ofl.AddLine(text);
}
}
}