【问题标题】:How to force UI automation tree refresh如何强制 UI 自动化树刷新
【发布时间】:2020-10-09 09:02:32
【问题描述】:

我目前正在尝试使用 System.Windows.Automation 自动化 chrome 实例,但在某个时刻 AutomationElement.FindAll(TreeScope.Children, Condition.TrueCondition); 总是返回 0 个子级,但我可以在 inspect.exe 中看到它们。当我在 inspect.exe 中点击刷新时,元素也会显示在我的应用中。

在寻找解决方案时,我发现 this SO 帖子,该 OP 或多或少有相同的问题。 建议使用的答案:

SystemParametersInfo( SPI_SETSCREENREADER, TRUE, NULL, SPIF_UPDATEINIFILE | SPIF_SENDCHANGE);
PostMessage( HWND_BROADCAST, WM_WININICHANGE, SPI_SETSCREENREADER, 0);

我将其实现为:

[DllImport("user32.dll", SetLastError = true)]
static extern bool SystemParametersInfo(int uiAction, int uiParam, IntPtr pvParam, int fWinIni);

[DllImport("user32.dll")]
static extern bool PostMessage(IntPtr hWnd, uint Msg, int wParam, int lParam);

....

const int SPI_SETSCREENREADER = 0x0047;

IntPtr inptrnull = IntPtr.Zero;
const int SPIF_UPDATEINIFILE = 0x01;
const int SPIF_SENDCHANGE = 0x02;


IntPtr HWND_BROADCAST = new IntPtr(0xffff);
const int WM_WININICHANGE = 0x001A;

SystemParametersInfo(SPI_SETSCREENREADER, 1, inptrnull, SPIF_UPDATEINIFILE | SPIF_SENDCHANGE);
PostMessage(HWND_BROADCAST, WM_WININICHANGE, SPI_SETSCREENREADER, 0);

但是没有效果。

我错过了什么? 还有其他/更好的方法吗?

【问题讨论】:

    标签: c# user-interface ui-automation inspect.exe


    【解决方案1】:

    看起来您使用的是过时的托管 UIA 实现 (System.Windows.Automation)。 这是一个已知的案例,它不能返回所有的孩子,这可能是原因。

    根据documentation

    对于 Windows 7,API 已在组件对象中重写 型号 (COM)。虽然前面介绍的库函数 UI 自动化的版本仍然记录在案,它们不应该被使用 在新应用中。

    您可以尝试改用UIA COM interface(Inspect 使用相同的方法):

    1. 向您的项目添加对 COM -> UIAutomationClient 的引用。这将为您生成一个包装器,因此可以在代码中以通常的 OO 样式访问 COM 接口。

    2. 创建一个 UI 自动化对象并使用 UIA 元素完成您的工作:

      IUIAutomation automation = new CUIAutomation();
      // Start with the root element; you could also get an element from the point or current focus
      IUIAutomationElement element = automation.GetRootElement();
      IUIAutomationElementArray foundElements = element.FindAll(TreeScope.TreeScope_Children, automation.CreateTrueCondition());
      for (int i = 0; i < foundElements.Length; i++)
      {
          IUIAutomationElement currentElement = foundElements.GetElement(i);
          // do your stuff with the element: get its properties, etc
      }
      
    3. 如果上述方法没有帮助,您可以尝试使用 RawTreeWalker 而不是调用 FindAll() 来遍历 UI 树:

      IUIAutomationTreeWalker walker = automation.RawViewWalker;
      IUIAutomationElement child = walker.GetFirstChildElement(element);
      var sibling = walker.GetNextSiblingElement(child);
      while (sibling != null)
      {
          // do your stuff with sibling elements (get their child elements, etc)
          sibling = walker.GetNextSiblingElement(child);
      }
      
    4. 我之前使用 UIA 自动化了 Chrome,据我所知,它对 UIA 调用的响应可能有点奇怪:例如有时它会返回一个容器元素而不是实际的元素(按钮、编辑等)。我通过多次尝试解决了这个案例,直到我最终检索到预期的结果。如果你也多次调用 FindAll() 会怎样?

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2019-09-22
      • 2015-12-14
      • 2019-04-27
      • 1970-01-01
      • 1970-01-01
      • 2012-12-15
      • 1970-01-01
      相关资源
      最近更新 更多