使用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; }
复现步骤
- 在任意浏览器中登录Spotify官网;
- 点击右下角音量按钮旁的“Open MiniPlayer”,打开名为“Spotify MiniPlayer”的新窗口;
- 对窗口进行调整大小、点击按钮等操作后运行上述代码;
- 观察检测结果:有时能检测到按钮,有时不能,未检测到时只能反复重启窗口直至成功。
疑问
是否UIA调用了某些操作使控件完成了初始化?
内容的提问来源于stack exchange,提问作者Renan
相关产品推荐
相关产品推荐

