예제 #1
0
        public static string GetAutomationIdOfUiElement(RecordedUiTask recordedUiTask, List <string> pathNodes, ref UiTreeNode rootRet)
        {
            string lastValidAutomationId = string.Empty;

            rootRet = null;

            string tag, ClassName, Name, AutomationId, Pos;
            string xPath = "";

            UiTreeNode parent = null;

            for (int i = 0; i < pathNodes.Count; i++)
            {
                var nodePath = pathNodes[i];

                bool bStartsWithName   = false;
                bool bStartsWithClass  = false;
                bool bStartsWithAutoId = false;

                var tagAttrs = GetTagAttributes(nodePath);

                tag = tagAttrs.ContainsKey("Tag") ? tagAttrs["Tag"] : "Unknown";

                AutomationId = tagAttrs.ContainsKey("AutomationId") ? tagAttrs["AutomationId"] : null;

                Name = tagAttrs.ContainsKey("Name") ? tagAttrs["Name"] : null;

                ClassName = tagAttrs.ContainsKey("ClassName") ? tagAttrs["ClassName"] : null;
                ClassName = CheckAndFixNoneStaticValue(ClassName);

                Pos = tagAttrs.ContainsKey("position()") ? tagAttrs["position()"] : null;

                string xPathNode = $"/{tag}";

                // Set AutomationId to null if it is a GUID which is very likely generated at runtime
                AutomationId = CheckAndFixNoneStaticValue(AutomationId);

                // AutomationId (like UIs on Cortana search result list) created at runtime may end with digits
                if (!string.IsNullOrEmpty(AutomationId) && !AutomationId.StartsWith("starts-with:"))
                {
                    string patAutoIdEndsWithDigits = @"^([^\d]*)[_\.\-\d]+$";
                    System.Text.RegularExpressions.Regex regAutoId = new System.Text.RegularExpressions.Regex(patAutoIdEndsWithDigits, System.Text.RegularExpressions.RegexOptions.IgnoreCase);
                    if (regAutoId != null)
                    {
                        System.Text.RegularExpressions.Match matchAutoId = regAutoId.Match(AutomationId);
                        if (matchAutoId.Success && matchAutoId.Groups.Count > 1)
                        {
                            if (matchAutoId.Groups[1].Length > 0)
                            {
                                AutomationId      = "starts-with:" + matchAutoId.Groups[1].ToString();
                                bStartsWithAutoId = true;
                            }
                            else
                            {
                                AutomationId = null;
                            }
                        }
                    }
                }

                if (!string.IsNullOrEmpty(ClassName) && string.IsNullOrEmpty(AutomationId))
                {
                    if (ClassName.StartsWith("starts-with:"))
                    {
                        ClassName        = ClassName.Remove(0, "starts-with:".Length);
                        xPathNode       += string.Format(sNameStartsWithValue, "ClassName", ClassName);
                        bStartsWithClass = true;
                    }
                    else
                    {
                        xPathNode += string.Format(sNameValue, "ClassName", ClassName);
                    }
                }

                if (!string.IsNullOrEmpty(Name))
                {
                    if (Name.StartsWith("starts-with:"))
                    {
                        Name            = Name.Remove(0, "starts-with:".Length);
                        xPathNode      += string.Format(sNameStartsWithValue, "Name", Name);
                        bStartsWithName = true;
                    }
                    else
                    {
                        xPathNode += string.Format(sNameValue, "Name", Name);
                    }
                }

                if (!string.IsNullOrEmpty(AutomationId))
                {
                    if (AutomationId.StartsWith("starts-with:"))
                    {
                        AutomationId      = AutomationId.Remove(0, "starts-with:".Length);
                        xPathNode        += string.Format(sNameStartsWithValue, "AutomationId", AutomationId);
                        bStartsWithAutoId = true;
                    }
                    else
                    {
                        xPathNode += string.Format(sNameValue, "AutomationId", AutomationId);
                    }
                }

                if (!string.IsNullOrEmpty(Pos) && string.IsNullOrEmpty(AutomationId) && string.IsNullOrEmpty(Name) && string.IsNullOrEmpty(ClassName))
                {
                    xPathNode += $"[position()={Pos}]";
                }

                // UiTreeNode
                var left      = tagAttrs.ContainsKey("x") ? tagAttrs["x"] : null;
                var top       = tagAttrs.ContainsKey("y") ? tagAttrs["y"] : null;
                var leftLocal = tagAttrs.ContainsKey("lx") ? tagAttrs["lx"] : null;
                var topLocal  = tagAttrs.ContainsKey("ly") ? tagAttrs["ly"] : null;
                var width     = tagAttrs.ContainsKey("width") ? tagAttrs["width"] : null;
                var height    = tagAttrs.ContainsKey("height") ? tagAttrs["height"] : null;
                var runtimeId = tagAttrs.ContainsKey("RuntimeId") ? tagAttrs["RuntimeId"] : null;

                xPath += xPathNode;

                var uiTreeNode = new UiTreeNode(parent)
                {
                    Title = $"{tag}, \"{Name}\", {ClassName}"
                };

                uiTreeNode.NodePath                  = xPathNode;
                uiTreeNode.Tag                       = tag;
                uiTreeNode.ClassName                 = ClassName;
                uiTreeNode.Name                      = Name;
                uiTreeNode.AutomationId              = AutomationId;
                uiTreeNode.Left                      = left;
                uiTreeNode.Top                       = left;
                uiTreeNode.Width                     = width;
                uiTreeNode.Height                    = height;
                uiTreeNode.RuntimeId                 = runtimeId;
                uiTreeNode.Position                  = Pos;
                uiTreeNode.NameCompareMethod         = bStartsWithName ? UiTreeNode.CompareMethod.StartsWith : UiTreeNode.CompareMethod.Equal;
                uiTreeNode.ClassNameCompareMethod    = bStartsWithClass ? UiTreeNode.CompareMethod.StartsWith : UiTreeNode.CompareMethod.Equal;
                uiTreeNode.AutomationIdCompareMethod = bStartsWithAutoId ? UiTreeNode.CompareMethod.StartsWith : UiTreeNode.CompareMethod.Equal;

                if (i == pathNodes.Count - 1)
                {
                    uiTreeNode.UiTask        = recordedUiTask;
                    recordedUiTask.Left      = left;
                    recordedUiTask.Top       = top;
                    recordedUiTask.LeftLocal = leftLocal;
                    recordedUiTask.TopLocal  = topLocal;
                    recordedUiTask.Name      = Name;
                    recordedUiTask.Tag       = tag;
                }

                if (rootRet == null)
                {
                    rootRet = uiTreeNode;
                }

                if (parent != null)
                {
                    parent.Items.Add(uiTreeNode);
                }

                parent = uiTreeNode;

                lastValidAutomationId = string.IsNullOrEmpty(AutomationId) ? lastValidAutomationId : AutomationId;
            }

            return(lastValidAutomationId);
        }
예제 #2
0
        static string GetXPathFromUiTaskNode(XmlElement uiTaskNode)
        {
            if (uiTaskNode == null || uiTaskNode.ChildNodes.Count < 1)
            {
                return("");
            }

            string tag, ClassName, Name, AutomationId, Pos;
            string xPath = "";

            for (int i = 0; i < uiTaskNode.ChildNodes.Count; i++)
            {
                XmlNode childNode = uiTaskNode.ChildNodes[i];

                tag          = childNode.Name != "Unknown" ? childNode.Name : "*";
                AutomationId = XmlEncode(childNode.Attributes[ConstVariables.AutomationId].Value);
                AutomationId = CheckAndFixNoneStaticValue(AutomationId);

                Name = XmlEncode(childNode.Attributes[ConstVariables.Name].Value);

                ClassName = childNode.Attributes[ConstVariables.ClassName].Value;
                ClassName = CheckAndFixNoneStaticValue(ClassName);
                Pos       = childNode.Attributes[ConstVariables.Pos].Value;

                xPath += $"/{tag}";
                int nPos = xPath.Length;

                // AutomationId (like UIs on Cortana search result list) created at runtime may end with digits
                if (!string.IsNullOrEmpty(AutomationId) && !AutomationId.StartsWith("starts-with:"))
                {
                    string patAutoIdEndsWithDigits = @"^([^\d]*)[\d]+$";
                    System.Text.RegularExpressions.Regex regAutoId = new System.Text.RegularExpressions.Regex(patAutoIdEndsWithDigits, System.Text.RegularExpressions.RegexOptions.IgnoreCase);
                    if (regAutoId != null)
                    {
                        System.Text.RegularExpressions.Match matchAutoId = regAutoId.Match(AutomationId);
                        if (matchAutoId.Success && matchAutoId.Groups.Count > 1)
                        {
                            if (matchAutoId.Groups[1].Length > 0)
                            {
                                AutomationId = "starts-with:" + matchAutoId.Groups[1].ToString();
                            }
                            else
                            {
                                AutomationId = null;
                            }
                        }
                    }
                }

                if (!string.IsNullOrEmpty(AutomationId))
                {
                    if (AutomationId.StartsWith("starts-with:"))
                    {
                        AutomationId = AutomationId.Remove(0, "starts-with:".Length);
                        xPath       += string.Format(sNameStartsWithValue, ConstVariables.AutomationId, AutomationId);
                    }
                    else
                    {
                        xPath += string.Format(sNameValue, ConstVariables.AutomationId, AutomationId);
                    }
                }

                if (!string.IsNullOrEmpty(Name))
                {
                    if (Name.StartsWith("starts-with:"))
                    {
                        Name   = Name.Remove(0, "starts-with:".Length);
                        xPath += string.Format(sNameStartsWithValue, ConstVariables.Name, Name);
                    }
                    else
                    {
                        xPath += string.Format(sNameValue, ConstVariables.Name, Name);
                    }
                }

                if (!string.IsNullOrEmpty(ClassName) && string.IsNullOrEmpty(AutomationId))
                {
                    if (ClassName.StartsWith("starts-with:"))
                    {
                        ClassName = ClassName.Remove(0, "starts-with:".Length);
                        xPath    += string.Format(sNameStartsWithValue, ConstVariables.ClassName, ClassName);
                    }
                    else
                    {
                        xPath += string.Format(sNameValue, ConstVariables.ClassName, ClassName);
                    }
                }

                if (!string.IsNullOrEmpty(Pos) && string.IsNullOrEmpty(AutomationId) && string.IsNullOrEmpty(Name) && string.IsNullOrEmpty(ClassName))
                {
                    //TODO: verify
                    xPath = xPath.Insert(nPos, $"[position()={Pos}]");
                }
            }

            return("\"" + xPath + "\",\n");
        }