You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用MSAA检测Spotify MiniPlayer按钮随机失败的技术问询

MSAA检测Spotify MiniPlayer按钮随机性问题

问题现象

使用MSAA检测Spotify MiniPlayer窗口的“Previous”和“Next”按钮时,存在随机无法检测的情况:必须反复重启窗口才可能成功检测。一旦检测成功,只要不重启窗口就一直有效,重启后又恢复随机状态。

排查结果

已排除时序或焦点问题:即使等待数小时、调整窗口大小、点击所有按钮,检测结果仍无规律,随机性依旧存在。

关键发现

使用微软Inspect工具测试时,捕捉到以下特殊场景:

  • 未检测到控件时,选择MSAA选项无法找到按钮;
  • 仅切换至UI Automation选项(无需聚焦或修改窗口),按钮即可被检测到;
  • 切回MSAA选项后,控件也能被正确检测;
  • 用UIA选项Inspect窗口后,即使重新创建Spotify MiniPlayer窗口,MSAA也能始终成功检测按钮。

由于UI Automation在窗口处于后台或隐藏状态时无法正常工作,因此希望继续使用MSAA方案。

检测按钮的C++代码

#include <iostream>
#include <Windows.h>
#include <oleacc.h>
#pragma comment(lib, "oleacc.lib")

void printElementInfo(IAccessible* pAcc, long childId)
{
    VARIANT varChild;
    varChild.vt = VT_I4;
    varChild.lVal = childId;
    BSTR bstrName;
    if (pAcc->get_accName(varChild, &bstrName) == S_OK)
    {
        std::wstring ws(bstrName);
        if (ws == L"Previous") // Button found!!
            OutputDebugStringW(ws.c_str());
        SysFreeString(bstrName);
    }
}

void iterateOverElements(IAccessible* pAcc)
{
    long childCount, returnCount;
    pAcc->get_accChildCount(&childCount);

    if (childCount > 0)
    {
        VARIANT* pArray = new VARIANT[childCount];
        if (AccessibleChildren(pAcc, 0L, childCount, pArray, &returnCount) == S_OK)
        {
            for (int i = 0; i < returnCount; i++)
            {
                if (pArray[i].vt == VT_DISPATCH)
                {
                    IDispatch* pDisp = pArray[i].pdispVal;
                    IAccessible* pChild = NULL;

                    if (pDisp->QueryInterface(IID_IAccessible, (void**)&pChild) == S_OK)
                    {
                        printElementInfo(pChild, CHILDID_SELF);
                        iterateOverElements(pChild);
                        pChild->Release();
                    }
                    else
                        OutputDebugStringW(L"Failed to query interface for child.\n");
                }

                else if (pArray[i].vt == VT_I4)
                    printElementInfo(pAcc, pArray[i].lVal);

                else
                    OutputDebugStringW(L"Unknown child type.\n");
            }
        }
        else
            OutputDebugStringW(L"Failed to get accessible children.\n");
        delete[] pArray;
    }
}

int main()
{
    CoInitialize(NULL);
    HWND hwnd = FindWindow(L"Chrome_WidgetWin_1", NULL);
    if (!hwnd)
    {
        OutputDebugStringW(L"Failed to find window.\n");
        return -1;
    }

    IAccessible* pAcc = NULL;
    if (AccessibleObjectFromWindow(hwnd, OBJID_WINDOW, IID_IAccessible, (void**)&pAcc) != S_OK)
    {
        OutputDebugStringW(L"Failed to get accessible object from window.\n");
        return -1;
    }

    iterateOverElements(pAcc);
    pAcc->Release();
    CoUninitialize();
    return 0;
}

复现步骤

  1. 在任意浏览器中登录Spotify官网;
  2. 点击右下角音量按钮旁的“Open MiniPlayer”,打开名为“Spotify MiniPlayer”的新窗口;
  3. 对窗口进行调整大小、点击按钮等操作后运行上述代码;
  4. 观察检测结果:有时能检测到按钮,有时不能,未检测到时只能反复重启窗口直至成功。

疑问

是否UIA调用了某些操作使控件完成了初始化?


内容的提问来源于stack exchange,提问作者Renan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.22 05:44:54