问题描述
- 使用MSA技术获取MS Edge浏览器的输入地址,为什么win10 32位能够获取而64位无法获取?
-
#include
#pragma comment(lib, "comsuppw.lib")#include
#include
#include
#pragma comment( lib, "Oleacc.lib")// --------------------------------------------------------------------------
//
// GetObjectName()
//
// This gets the name of an object.
//
// --------------------------------------------------------------------------
UINT GetObjectName(IAccessible* pacc, VARIANT* pvarChild, LPTSTR lpszName, UINT cchName)
{
CString str;
HRESULT hr;
BSTR bstrName;*lpszName = 0; bstrName = NULL; hr = pacc->get_accName(*pvarChild, &bstrName); if (SUCCEEDED(hr) && bstrName) { _tcsncpy_s(lpszName, MAX_PATH,bstrName, _tcslen(bstrName)); } return(lstrlen(lpszName));
}
UINT GetObjectState(IAccessible* pacc, VARIANT* pvarChild, LPTSTR lpszState, UINT cchState)
{
CString str;
HRESULT hr;
VARIANT varRetVal;*lpszState = 0; VariantInit(&varRetVal); hr = pacc->get_accState(*pvarChild, &varRetVal); if (!SUCCEEDED(hr)) return(0); DWORD dwStateBit; int cChars = 0; if (varRetVal.vt == VT_I4) { // Convert state flags to comma separated list. for (dwStateBit = STATE_SYSTEM_UNAVAILABLE; dwStateBit < STATE_SYSTEM_ALERT_HIGH; dwStateBit <<= 1) { if (varRetVal.lVal & dwStateBit) { cChars += GetStateText(dwStateBit, lpszState + cChars, cchState - cChars); *(lpszState + cChars++) = ','; } } if(cChars > 1) *(lpszState + cChars - 1) = ''; } else if (varRetVal.vt == VT_BSTR) { _tcsncpy_s(lpszState, MAX_PATH, varRetVal.bstrVal, _tcslen(varRetVal.bstrVal)); } VariantClear(&varRetVal); return(lstrlen(lpszState));
}
// --------------------------------------------------------------------------
//
// GetObjectClass()
//
// This gets the Class of an object.
//
// --------------------------------------------------------------------------
UINT GetObjectClass(IAccessible* pacc, LPTSTR lpszClass, UINT cchClass)
{
HWND hWnd;
if(S_OK == WindowFromAccessibleObject(pacc, &hWnd))
{
if(hWnd)
GetClassName(hWnd, lpszClass, cchClass);
else
_tcscpy(lpszClass, _T("No window"));
}return 1;
}
// --------------------------------------------------------------------------
//
// GetObjectRole()
//
// --------------------------------------------------------------------------
UINT GetObjectRole(IAccessible* pacc, VARIANT* pvarChild, LPTSTR lpszRole, UINT cchRole)
{
CString str;
HRESULT hr;
VARIANT varRetVal;*lpszRole = 0; VariantInit(&varRetVal); hr = pacc->get_accRole(*pvarChild, &varRetVal); if (!SUCCEEDED(hr)) return(0); if (varRetVal.vt == VT_I4) { //the function GetRoleText use to translate the int to the Role string. GetRoleText(varRetVal.lVal, lpszRole, cchRole); } else if (varRetVal.vt == VT_BSTR) { _tcsncpy_s(lpszRole, MAX_PATH, varRetVal.bstrVal, _tcslen(varRetVal.bstrVal)); } VariantClear(&varRetVal); return(lstrlen(lpszRole));
}
bool EnumUIChild(IAccessible* paccParent, IAccessible** paccChild, VARIANT* pvarChild)
{
CString str;
HRESULT hr;
long numChildren = 0;
unsigned long numFetched;
VARIANT varChild;
int index;
IAccessible* pCAcc = NULL;
IEnumVARIANT* pEnum = NULL;
IDispatch* pDisp = NULL;
bool found = false;TCHAR szObjName[MAX_PATH] = {0}; TCHAR szObjRole[MAX_PATH] = {0}; TCHAR szObjClass[MAX_PATH] = {0}; TCHAR szObjState[MAX_PATH] = {0}; //Get the IEnumVARIANT interface hr = paccParent -> QueryInterface(IID_IEnumVARIANT, (PVOID*) & pEnum); if(pEnum) pEnum -> Reset(); // Get child count paccParent -> get_accChildCount(&numChildren); for(index = 1; (index <= numChildren) && (found == false); index++) { pCAcc = NULL; // Get next child if (pEnum) hr = pEnum -> Next(1, &varChild, &numFetched); else { //if the farther don't support IEnumVARIANT interface丆 //ID equal index. varChild.vt = VT_I4; varChild.lVal = index; } // Get IDispatch interface for the child if (varChild.vt == VT_I4) { //Get Dispatch interface from ID. pDisp = NULL; hr = paccParent -> get_accChild(varChild, &pDisp); } else //if the farther support IEnumVARIANT interface, //Get the child's IDispatch interface directly. pDisp = varChild.pdispVal; // Get IAccessible interface for the child if (pDisp) { hr = pDisp->QueryInterface(IID_IAccessible, (void**)&pCAcc); hr = pDisp->Release(); } // Get information about the child if(pCAcc) { //if the leaf support IAccessible interface.ID equal CHILDID_SELF VariantInit(&varChild); varChild.vt = VT_I4; varChild.lVal = CHILDID_SELF; *paccChild = pCAcc; } else //if the leaf do not support IAccessible interface. *paccChild = paccParent; // Skip invisible and unavailable objects and their children GetObjectState(*paccChild, &varChild, szObjState, sizeof(szObjState)); if(NULL != _tcsstr(szObjState, _T("unavailable"))) { if(pCAcc) pCAcc->Release(); continue; } GetObjectName(*paccChild, &varChild, szObjName, sizeof(szObjName)); GetObjectRole(*paccChild, &varChild, szObjRole, sizeof(szObjRole)); GetObjectClass(*paccChild, szObjClass, sizeof(szObjClass)); CString strRole = szObjRole; CString strName = szObjName; if(/*(0 == strName.Compare(_T("搜索或输入网址")) && 0 == strRole.Compare(_T("可编辑文本"))) || (0 == strName.Compare(_T("Address and search bar")) && 0 == strRole.Compare(_T("editable text"))) || (0 == strName.Compare(_T("Address and search bar")) && 0 == strRole.Compare(_T("可编辑文本"))) || (0 == strName.Compare(_T("搜索或输入网址")) && 0 == strRole.Compare(_T("editable text")))*/ 0 == strRole.Compare(_T("可编辑文本"))) { found = true; *pvarChild = varChild; break; } if(!found && pCAcc) { found = EnumUIChild(pCAcc, paccChild, pvarChild); if(*paccChild != pCAcc) pCAcc->Release(); if(found == true) return true; } } if(pEnum) pEnum -> Release(); return found;
}
CString GetURLText()
{
TCHAR szEdit[1024]={0};
HWND hWnd = ::FindWindow(_T("ApplicationFrameWindow"),NULL);
hWnd = ::FindWindowEx(hWnd,0,L"Windows.UI.Core.CoreWindow",NULL);
if(NULL != hWnd)
{
IAccessible paccMainWindow = NULL;
HRESULT hr;
CString strM;
//Get IAccessible Interface Point
if(S_OK == (hr = AccessibleObjectFromWindow(hWnd,
OBJID_WINDOW,
IID_IAccessible,
(void*)&paccMainWindow)))
{
int index;
BOOL found = false;
IAccessible* paccControl = NULL;
VARIANT varControl;
CoInitialize(NULL);if(true == EnumUIChild(paccMainWindow, &paccControl, &varControl)) { BSTR bstrURL; hr = paccControl->get_accValue(varControl,&bstrURL); if( DISP_E_MEMBERNOTFOUND == hr) { ::MessageBox(NULL,L"DISP_E_MEMBERNOTFOUND",L"msg",NULL); } else if( E_INVALIDARG == hr) { ::MessageBox(NULL,L"E_INVALIDARG",L"msg",NULL); } else if( S_OK == hr) { ::MessageBox(NULL,L"S_OK",L"msg",NULL); } if(SUCCEEDED(hr) &&bstrURL) { char* szEdit1 = _com_util::ConvertBSTRToString(bstrURL); mbstowcs(szEdit, szEdit1, MAX_PATH); ::SysFreeString( bstrURL ); } paccControl->Release(); VariantClear(&varControl); }; paccMainWindow->Release(); } } return szEdit;
}
上面是完整代码,在win10 32位上能够获取到浏览器输入的地址,而win10 64位上找到的地址栏元素无法使用get_accValue()获取网址,根据返回值发现,该对象不支持此属性。
解决方案
更新下操作系统,问题解决。