【问题标题】:AutoIT, or User32 button clicking working sporadicallyAutoIT 或 User32 按钮偶尔单击工作
【发布时间】:2012-03-02 06:11:00
【问题描述】:

我正在尝试自动化应用程序的测试,但我遇到了一个我正在努力解决的问题。

该应用程序具有标准的 Windows 按钮,我尝试使用 AutoIT 和 User32 dll 来单击其中一些按钮。有时按钮被正确点击(耶!),有时它们失败(嘘!) - 但更糟糕的是,AutoIT 确信它点击了按钮(双重嘘!)然后产生误报(三声嘘!)。当我看到它被说服时,我的意思是它返回点击成功而不是成功。

我在 Win Server 2K8 上运行该应用程序,该应用程序除了使用 MDI 窗口之外没有什么特别之处,并且一些按钮包含在 MDI 窗口中。但有些不在 MDI 窗口中(例如,在创建父窗口之前的登录窗口)。

这是我的命令顺序:

在窗口中找到按钮(总是成功) 将窗口置于前台(成功) 激活窗口(成功) 激活按钮(成功) 聚焦按钮(成功) 如果按钮已获得焦点,并且该按钮已启用,则单击它。 (成功/失败,不可预知的行为。我无法缩小它为什么有时会成功,以及为什么有时会失败......)

其他细节:

有时订单会点击按钮,这应该会打开另一个窗口。该窗口关闭,然后再次单击该按钮 - 这一次,没有任何反应。其他时候它按预期工作。

我以管理员身份运行,UAC 已完全禁用。

据我所知,这不是时间问题,因为我确实确保按钮已获得焦点,并在尝试单击它之前启用,并且我看到按钮确实在其周围获得了焦点突出显示。

正如我所提到的,我也一直在尝试通过简单的 User32/SendMessage 调用来实现这一点,但这也失败了。

最后但同样重要的是,当我手动与应用程序交互时不会发生这种情况。我一直有实际的按钮点击工作。

有什么想法吗?

更新

这是我应该提到的等式的另一个变量 - 这发生在 VM 上(因为这是我需要运行它的地方)。我可以在我自己的机器上做一些有限的测试,但要获得一些真正的测试,它需要在 VM 上。点击我自己的开发框似乎是可靠的,这让这更加令人费解。

我一直在另一个 VM 上尝试这个,它似乎也在那里工作。就这两个虚拟机而言,它们运行的​​是相同版本的 Windows、相同版本的我的应用程序、相同版本的 AutoIT,等等。

我已将其简化为一个细节 - 幸运的是,我无法自行配置,必须提交一张票才能更改任何配置。配置的区别是这样的:

工作的 VM 上,设备管理器显示一个鼠标,它是 vmware 鼠标。在 工作的 VM 上,设备管理器显示一个 PS/2 鼠标。显然两者都是软件鼠标,但我现在想知道 VMWare 鼠标的行为是否会有所不同,并导致按钮点击并不总是有效。我不确定这作为解决方案的可能性有多大,因为根据我对它的理解,使用 User32 SendMessage 调用实际上并不使用鼠标,而是发送鼠标会发送的相同消息,但值得一试...

【问题讨论】:

  • 有多个子窗体,但每个窗体一次只有一个实例 - 我可以确认包含按钮 的窗口位于顶部,并且是没有被最上面的窗户挡住
  • 我正在使用以下命令:ControlClick("My Sub Window Title", "", "CLASS:ThunderRT6CommandButton; INSTANCE:1]", "left");我不设置坐标,因为我总是提供控件 ID(谢天谢地,这是静态的)
  • 我很确定当 AutoIt 确信它找到了按钮时,它也点击了它。换句话说:它只会在找不到控件时返回错误。这只是一个正在发送的 Windows 消息,当其他应用程序不处理它时,AutoIt 无法知道。
  • 尝试使用来自@M.Babcock 的提示并正确定位鼠标并单击。有一个功能_WinAPI_ClientToScreen 可以帮助您获得点击的确切屏幕位置。使用来自ControlGetPos 的坐标输入它。或者您应该在再次单击该按钮之前的某个时间点 Sleep(333),或者使用 Send("{Space}") 模拟单击​​,因为您已经将焦点放在了它上面。
  • 我确实在我的 User32 调用中使用睡眠来发送点击。我已经设置了我的代码来尝试 AutoIT,然后如果失败则回退到 User32 - 但误报是问题所在。这可能是一个显而易见的问题,但如果我遗漏了什么 - 是否有任何潜在的消息可以挂钩以验证按钮是否已被按下?显然,我可以一起破解一些东西,但是我可以绑定任何底层的 Windows 消息来验证按钮是否接收到某种“点击”状态 - 也许如果它的类从未点击的按钮类更改为点击的,或者类似的东西?

标签: c# windows automation autoit user32


【解决方案1】:

您说您已成功Focused 按钮,那么您是否尝试过发送Spacebar 事件而不是MouseClick

Send("{SPACE}")

(我认为这是语法。我不是 AutoIt 的常客)

空格键通常可用于与大多数可点击控件进行交互,例如按钮和复选框。以我的经验,模拟鼠标点击,甚至ControlClicks,由于奇怪的、不一致的原因,远不如击键可靠。我的同情。

至于检测按钮被点击,也许最简单的方法是让按钮更改AutoIT 可以检测到的表单。例如,在用户按下按钮之前读取Ready 的状态标签。当用户按下按钮时,文本变为Processing。如有必要,您可以使标签不可见(或位于表单边界之外),这样用户就看不到它,但 AutoIt 可以。

【讨论】:

    【解决方案2】:

    在您发布此问题时,您可能已成功解决此问题,但还没有好的答案,所以我会发布我的:

    我在运行 Windows Server 2008 R2 的虚拟机上遇到了同样的问题:我无法通过 Win32 API SendMessage 向特定程序(及其主窗口)发送击键或执行任何操作。

    根据Q/A,这是一个 UIPI 问题(自 Windows Vista 以来就存在)。您只需关闭 UAC 即可解决此问题。我测试了它并且它有效。可以通过我提供的链接找到更多替代方案。

    【讨论】:

      【解决方案3】:

      我已经模拟了你的情况,它在 Windows 7 上 100% 运行:

      using System.Runtime.InteropServices;
      
      [DllImport("user32.dll", SetLastError = true)]
      static extern void keybd_event(byte bVk, byte bScan, uint dwFlags, UIntPtr dwExtraInfo);
      
      void ClickFocusedControl()
      {
          const uint KEYEVENTF_EXTENDEDKEY = 0x1;
          const uint KEYEVENTF_KEYUP  = 0x2;
      
          keybd_event(13, Convert.ToByte(0), KEYEVENTF_EXTENDEDKEY, UIntPtr.Zero); //Generates a KEY_DOWN
          keybd_event(13, Convert.ToByte(0), KEYEVENTF_KEYUP, UIntPtr.Zero); // Generates a KEY_UP
      }
      

      【讨论】:

        猜你喜欢
        • 2019-08-21
        • 2021-09-14
        • 1970-01-01
        • 1970-01-01
        • 2014-07-18
        • 2013-05-30
        • 2016-04-08
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多