UI 自动化看不到隐藏的窗口?



我有 winforms 应用程序,该应用程序已签名并具有 level="requireAdministrator" uiAccess="false" 的清单。
我想使用隐藏窗口启动另一个应用程序,并使用UI 自动化 API 使用它。

        Process procinst = new Process();
        procinst.StartInfo = new ProcessStartInfo()
        {
            WindowStyle = ProcessWindowStyle.Hidden,
            UseShellExecute = true,
            ErrorDialog = true,
            Verb = "runas",
            FileName = appfilepath
        };           
        procinst.Start();

带有隐藏窗口的新进程可以在 Spy++ 中看到,但在 UISpy 中看不到,我也无法使用 FindFirst 方法找到它:

mainwnd = AutomationElement.RootElement.FindFirst(TreeScope.Descendants, new PropertyCondition(AutomationElement.NameProperty, "apptitle"));

当ProcessWindowStyle最小化时,一切都会正常,当它被隐藏时 - 一切都停止了。
是否是预期的 UI 自动化行为?UI 自动化无法访问隐藏的窗口?有什么办法可以破解它吗?

根据 MSDN,"以编程方式隐藏"的 UI 元素不应位于UI 自动化树中。

特别:

UIA_IsOffscreenPropertyId (30022) 标识屏幕外 属性,这是一个布尔值,指示是否 自动化元素完全滚动到视图之外(例如,一个 列表框中位于容器视区之外的项 对象)或折叠在视图之外(例如,树视图中的项) 或菜单,或在最小化的窗口中)。如果元素具有可点击的 可能导致它接收焦点的点,该元素是 被视为在部分元素关闭时显示在屏幕上 屏幕。 属性的值不受遮挡的影响 其他窗口,或者通过元素是否在特定窗口上可见 监控。 如果 IsOffscreen 属性为 TRUE,则 UI 元素为 在屏幕外滚动或折叠。元素暂时隐藏, 然而,它仍然在最终用户的认知中,并继续存在 包含在 UI 模型中。对象可以通过以下方式重新进入视图 滚动、单击下拉列表等。 最终用户的对象 根本感知不到,或者"以编程方式隐藏"(对于 例如,已关闭的对话框,但下划线 对象仍由应用程序缓存)不应位于 首先是自动化元素树(而不是设置 状态 IsOffscreen 为 TRUE)。

这很可悲,但这是真的:

UIA中并没有真正的"不可见"或"背景"元素这样的东西 - 当一个元素消失时,它将不再在UIA树中。这对于辅助技术来说是一件好事(需要较少的树修剪),但对于UI 自动化框架来说可能很麻烦。从历史上看,我们倾向于缓存UI元素,以便我们可以更快地再次返回它们。当需要时,可以调用ShowWindow和accSelect的混合SELFLAG_TAKEFOCUS。这不再有效。例如,如果工具窗口是选项卡式的,而不是在前台;我们的缓存元素将因为无效,如果请求它,我们需要 a) 将其置于前台和 b) 再次从头开始查找元素。

Visual Studio 2010 中的 WPF – 第 6 部分:自动化 UI 测试

最新更新