uiautomation未能找到子节点

发布于 2025-01-24 21:33:18 字数 186 浏览 2 评论 0 原文

试图自动化IIS(INETMGR)尝试使用UIAUTomation,我正在解决混合的结果。如果屏幕元素很好,我能够得到一些,其他,甚至是直接的孩子节点,都无法找到[first | all]或在树walk虫(内容| Control | Raw)中尝试,只是可以' t获取所需的节点。有什么建议用于驱动UI自动化它的方法?

窗口10/11桌面环境。

Trying to automate IIS (INetMgr) trying to use UIAutomation, i'm fixing mixed results. I'm able to get some if the screen elements good fine, others, even immediate children nodes, can't get either with a Find[First|All] or try in a treewalker (content|control|raw), just can't get the node(s) needed. Any suggestion what to use for driving the UI to automate it?

Window 10/11 desktop environment.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

像你 2025-01-31 21:33:18

这是一个C#控制台应用程序,可从“连接”窗格中转载Inetmgr项目的(最大2级)。

必须以管理员的身份启动,否则它将失败(不立即)。一般而言,UIA客户端必须在UAC级别上运行与自动化应用程序相同的UAC级别。

要确定从树中获得什么或是否可以完成任何操作,在任何编码之前,我们可以使用从Windows SDK 或最新的

另外,我使用Windows的uiautomationclient com对象,而不是Windows XP时代的旧版本,因为它错过了很多东西。

代码迭代所有递归使用因为Inetmgr的树具有懒惰的加载行为,因为它可能包含数十万个项目(在某些点映射到磁盘文件夹)。

class Program
{
    // add a COM reference to UIAutomationClient (don't use .NET legacy UIA .dll)
    private static readonly CUIAutomation8 _automation = new CUIAutomation8(); // using UIAutomationClient;

    static void Main()
    {
        var process = Process.GetProcessesByName("InetMgr").FirstOrDefault();
        if (process == null)
        {
            Console.WriteLine("InetMgr not started.");
            return;
        }

        var inetmgr = _automation.ElementFromHandle(process.MainWindowHandle);
        if (inetmgr == null)
            return;

        // note: set "Embed Interop Type" to false in UIAutomationClient reference node or redefine all UIA_* used constants manually
        // also: you *must* this program as administrator to see this panel
        var connections = inetmgr.FindFirst(TreeScope.TreeScope_Subtree,
            _automation.CreatePropertyCondition(UIA_PropertyIds.UIA_AutomationIdPropertyId, "_hierarchyPanel"));
        if (connections == null)
            return;

        var treeRoot = connections.FindFirst(TreeScope.TreeScope_Subtree,
            _automation.CreatePropertyCondition(UIA_PropertyIds.UIA_ControlTypePropertyId, UIA_ControlTypeIds.UIA_TreeItemControlTypeId));

        Dump(0, treeRoot);
    }

    static void Dump(int indent, IUIAutomationElement element)
    {
        var s = new string(' ', indent);
        Console.WriteLine(s + "name: " + element.CurrentName);

        // get expand/collapse pattern. All treeitem support that
        var expandPattern = (IUIAutomationExpandCollapsePattern)element.GetCurrentPattern(UIA_PatternIds.UIA_ExpandCollapsePatternId);
        if (expandPattern != null && expandPattern.CurrentExpandCollapseState != ExpandCollapseState.ExpandCollapseState_Expanded)
        {
            try
            {
                expandPattern.Expand();
            }
            catch
            {
                // cannot be expanded
            }
        }

        // tree can be huge,only dump 2 levels max
        if (indent > 2)
            return;

        var children = element.FindAll(TreeScope.TreeScope_Children, _automation.CreateTrueCondition());
        for (var i = 0; i < children.Length; i++)
        {
            Dump(indent + 1, children.GetElement(i));
        }
    }
}

Here is a C# Console app that dumps (max 2 levels) of InetMgr's items from the "Connections" pane.

This must be started as Administrator otherwise it will fail (not immediately). In general UIA clients must run at same UAC level as automated apps.

To determine what to get from the tree or if something can be done, before any coding, we can use the Inspect tool from Windows SDK or the more recent Accessibility Insights.

Also, I use Windows' UIAutomationClient COM object, not the old one from Windows XP era as it misses lots of stuff.

The code iterates all tree items recursively and expand them if they are not expanded using the ExpandCollapse Control Pattern because InetMgr's tree has a lazy loading behavior as it can potentially contains hundreds of thousands of items (mapped to disk folders at some points).

class Program
{
    // add a COM reference to UIAutomationClient (don't use .NET legacy UIA .dll)
    private static readonly CUIAutomation8 _automation = new CUIAutomation8(); // using UIAutomationClient;

    static void Main()
    {
        var process = Process.GetProcessesByName("InetMgr").FirstOrDefault();
        if (process == null)
        {
            Console.WriteLine("InetMgr not started.");
            return;
        }

        var inetmgr = _automation.ElementFromHandle(process.MainWindowHandle);
        if (inetmgr == null)
            return;

        // note: set "Embed Interop Type" to false in UIAutomationClient reference node or redefine all UIA_* used constants manually
        // also: you *must* this program as administrator to see this panel
        var connections = inetmgr.FindFirst(TreeScope.TreeScope_Subtree,
            _automation.CreatePropertyCondition(UIA_PropertyIds.UIA_AutomationIdPropertyId, "_hierarchyPanel"));
        if (connections == null)
            return;

        var treeRoot = connections.FindFirst(TreeScope.TreeScope_Subtree,
            _automation.CreatePropertyCondition(UIA_PropertyIds.UIA_ControlTypePropertyId, UIA_ControlTypeIds.UIA_TreeItemControlTypeId));

        Dump(0, treeRoot);
    }

    static void Dump(int indent, IUIAutomationElement element)
    {
        var s = new string(' ', indent);
        Console.WriteLine(s + "name: " + element.CurrentName);

        // get expand/collapse pattern. All treeitem support that
        var expandPattern = (IUIAutomationExpandCollapsePattern)element.GetCurrentPattern(UIA_PatternIds.UIA_ExpandCollapsePatternId);
        if (expandPattern != null && expandPattern.CurrentExpandCollapseState != ExpandCollapseState.ExpandCollapseState_Expanded)
        {
            try
            {
                expandPattern.Expand();
            }
            catch
            {
                // cannot be expanded
            }
        }

        // tree can be huge,only dump 2 levels max
        if (indent > 2)
            return;

        var children = element.FindAll(TreeScope.TreeScope_Children, _automation.CreateTrueCondition());
        for (var i = 0; i < children.Length; i++)
        {
            Dump(indent + 1, children.GetElement(i));
        }
    }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文