예제 #1
0
        public static void AddInspectUi(RecordedUiTask uiTask)
        {
            s_inspectUi = null;
            lock (RecordedUiTask.s_lockRecordedUi)
            {
                foreach (var recordedUi in RecordedUiTask.s_listRecordedUi)
                {
                    if (recordedUi.UiTaskName == EnumUiTaskName.Inspect)
                    {
                        s_inspectUi = recordedUi;
                        break;
                    }
                }

                if (uiTask != null)
                {
                    RecordedUiTask.s_listRecordedUi.Add(uiTask);

                    if (uiTask.UiTaskName != EnumUiTaskName.KeyboardInput)
                    {
                        UiTreeNode.AddToUiTree(uiTask);
                    }
                }
            }

            NativeMethods.PostMessage(MainWindow.s_windowHandle, (int)UiThreadTask.RemoveInspectNode, 0, 0);
            NativeMethods.PostMessage(MainWindow.s_windowHandle, (int)UiThreadTask.UpdateTreeView, 0, 0);
            if (uiTask != null)
            {
                NativeMethods.PostMessage(MainWindow.s_windowHandle, (int)UiThreadTask.XPathReady, 0, 0);
            }
        }
예제 #2
0
        private void DeleteRecordedUiTask(RecordedUiTask uiTask)
        {
            if (uiTask == null)
            {
                return;
            }

            lock (RecordedUiTask.s_lockRecordedUi)
            {
                if (uiTask.UiTaskName != EnumUiTaskName.KeyboardInput)
                {
                    UiTreeNode.RemoveUiTreeNode(uiTask);
                }

                RecordedUiTask.s_listRecordedUi.Remove(uiTask);

                if (RecordedUiTask.s_listRecordedUi.Count > 0)
                {
                    comboBoxRecordedUi.SelectedIndex = 0;
                    comboBoxRecordedUi.SelectedValue = RecordedUiTask.s_listRecordedUi[comboBoxRecordedUi.SelectedIndex];
                }
                else
                {
                    TextRange tr = new TextRange(rtbXPath.Document.ContentStart, rtbXPath.Document.ContentEnd);
                    tr.Text          = "";
                    textBoxCode.Text = "";
                }

                comboBoxRecordedUi.Items.Refresh();
                treeUiPath.Items.Refresh();
            }
        }
예제 #3
0
 public static bool CompareRuntimeId(UiTreeNode nodeLeft, UiTreeNode nodeRight)
 {
     if (nodeLeft == null || nodeRight == null)
     {
         return(false);
     }
     else
     {
         return(nodeLeft.RuntimeId == nodeRight.RuntimeId);
     }
 }
예제 #4
0
        static UiTreeNode FindInCachedUiTree(UiTreeNode node, List <UiTreeNode> cachedNode)
        {
            foreach (var snode in cachedNode)
            {
                if (CompareRuntimeId(node, snode))
                {
                    return(snode);
                }
            }

            return(null);
        }
예제 #5
0
        public static void AddToUiTree(RecordedUiTask recordedUi)
        {
            if (recordedUi.GetUiTreeNode() == null)
            {
                if (string.IsNullOrEmpty(recordedUi.GetXPath(false)))
                {
                    return;
                }
            }

            var uiNode = recordedUi.GetUiTreeNode();

            if (uiNode == null || uiNode.Items.Count == 0)
            {
                //Log error
                return;
            }

            // Empty root
            if (s_uiTreeNodes.Count == 0)
            {
                s_uiTreeNodes.Add(uiNode);
                return;
            }

            // Add uiNode to s_uiNode
            UiTreeNode        node       = uiNode;
            UiTreeNode        nodeCached = null;
            List <UiTreeNode> listCached = s_uiTreeNodes;

            while (node != null)
            {
                var nodeAddTo = FindInCachedUiTree(node, listCached);

                if (node.Items.Count > 0 && nodeAddTo != null)
                {
                    node       = node.Items.First();
                    listCached = nodeAddTo.Items;
                    nodeCached = nodeAddTo;
                }
                else
                {
                    if (nodeCached != null)
                    {
                        node.Parent = nodeCached;
                        nodeCached.Items.Add(node);
                    }
                    break;
                }
            }
        }
예제 #6
0
        public static void AddRecordedUi(RecordedUiTask uiTask)
        {
            lock (RecordedUiTask.s_lockRecordedUi)
            {
                RecordedUiTask.s_listRecordedUi.Add(uiTask);

                if (uiTask.UiTaskName != EnumUiTaskName.KeyboardInput)
                {
                    UiTreeNode.AddToUiTree(uiTask);
                }
            }

            NativeMethods.PostMessage(MainWindow.s_windowHandle, (int)UiThreadTask.UpdateTreeView, 0, 0);
        }
예제 #7
0
        public static void RemoveUiTreeNode(RecordedUiTask uiTaskNode)
        {
            if (s_uiTreeNodes.Count == 0)
            {
                return;
            }

            UiTreeNode uiNode = FindUiTaskNode(s_uiTreeNodes.First(), uiTaskNode);

            if (uiNode == null)
            {
                s_uiTreeNodes.Clear();
                return;
            }

            UiTreeNode uiParent = uiNode.Parent;

            if (uiParent == null)
            {
                s_uiTreeNodes.Clear();
                return;
            }

            while (uiParent != null)
            {
                uiNode.UiTask = null;

                if (uiNode.Items.Count == 0)
                {
                    uiParent.Items.Remove(uiNode);
                }

                if (uiParent.Items.Count > 0)
                {
                    break;
                }
                else
                {
                    uiNode   = uiParent;
                    uiParent = uiNode.Parent;
                }
            }

            if (uiParent == null && (s_uiTreeNodes.Count == 1 && s_uiTreeNodes.First().Items.Count == 0))
            {
                s_uiTreeNodes.Clear();
            }
        }
예제 #8
0
        static UiTreeNode FindUiTaskNode(UiTreeNode node, RecordedUiTask uiTaskNode)
        {
            if (node.UiTask == uiTaskNode)
            {
                return(node);
            }

            for (int i = 0; i < node.Items.Count; i++)
            {
                var ret = FindUiTaskNode(node.Items[i], uiTaskNode);
                if (ret != null)
                {
                    return(ret);
                }
            }

            return(null);
        }
예제 #9
0
        private TreeViewItem ExpandSelectedTreeNode(UiTreeNode uiTreeNode, TreeViewItem tvi, RecordedUiTask recordedUiTask)
        {
            if (tvi == null || uiTreeNode == null)
            {
                return(null);
            }

            if (uiTreeNode.Items.Count == 0)
            {
                if (uiTreeNode.UiTask == recordedUiTask)
                {
                    tvi.IsSelected = true;
                    return(tvi);
                }
                else
                {
                    return(null);
                }
            }

            // Collapse all
            foreach (var c in uiTreeNode.Items)
            {
                var subContainer = (TreeViewItem)tvi.ItemContainerGenerator.ContainerFromItem(c);
                if (subContainer != null)
                {
                    subContainer.IsExpanded = false;
                }
            }

            foreach (var c in uiTreeNode.Items)
            {
                var subContainer = (TreeViewItem)tvi.ItemContainerGenerator.ContainerFromItem(c);
                var ret          = ExpandSelectedTreeNode(c, subContainer, recordedUiTask);
                if (ret != null)
                {
                    subContainer.IsExpanded = true;
                    return(ret);
                }
            }

            return(null);
        }
예제 #10
0
        private RecordedUiTask GetExpandedLeafNode(TreeViewItem tvi, UiTreeNode node, RecordedUiTask recordedUiTask)
        {
            if (tvi == null || node == null)
            {
                return(null);
            }

            if (recordedUiTask != null)
            {
                if (node.UiTask == recordedUiTask)
                {
                    return(node.UiTask);
                }
            }
            else if (node.Items.Count == 0)
            {
                return(node.UiTask);
            }

            foreach (var c in node.Items)
            {
                var subContainer = (TreeViewItem)tvi.ItemContainerGenerator.ContainerFromItem(c);
                if (subContainer != null)
                {
                    if (subContainer.IsExpanded == true)
                    {
                        var retTemp = GetExpandedLeafNode(subContainer, c, recordedUiTask);
                        if (retTemp != null)
                        {
                            return(retTemp);
                        }
                    }
                }
            }

            return(null);
        }
예제 #11
0
        private TreeViewItem UiTreeNode2TreeViewItem(TreeViewItem tvi, UiTreeNode node, UiTreeNode nodeTarget)
        {
            if (tvi == null || node == null)
            {
                return(null);
            }

            if (node == nodeTarget)
            {
                return(tvi);
            }

            foreach (var c in node.Items)
            {
                var subContainer = (TreeViewItem)tvi.ItemContainerGenerator.ContainerFromItem(c);
                var ret          = UiTreeNode2TreeViewItem(subContainer, c, nodeTarget);
                if (ret != null)
                {
                    return(ret);
                }
            }

            return(null);
        }
예제 #12
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);
        }
예제 #13
0
 public UiTreeNode(UiTreeNode pNode)
 {
     Parent     = pNode;
     this.Items = new List <UiTreeNode>();
 }
예제 #14
0
 public WindowEditNodeAttribute(UiTreeNode uiNode)
 {
     InitializeComponent();
     uiTreeNode = uiNode;
 }