#cpp #internet_explorer #dom #com
Я хочу программно нажимать на кнопки сайта. Для этого решил использовать СОМ объект InternetExplorer. Выгрузить его в DOM и там уже кликать по кнопкам. Делаю это так: #include "stdafx.h" #include "windows.h" #import "progid:InternetExplorer.Application" int _tmain(int argc, _TCHAR* argv[]) { CoInitializeEx(NULL, COINIT_APARTMENTTHREADED); bool showIE = true; SHDocVw::IWebBrowserAppPtr ptrIE(_T("InternetExplorer.Application")); ptrIE->Visible = (showIE ? VARIANT_TRUE : VARIANT_FALSE); ptrIE->Navigate("https://vk.com"); int i = 0; // ждем пока загрузится страница по url while (ptrIE->Busy) i++; // получаем html-страницу как DOM (объектная модель документа) //auto pdisp = ptrIE->Document; IDispatch pdisp = (ptrIE->Document).GetInterfacePtr(); HRESULT hresult; DISPID dispid; OLECHAR *szMember = L"querySelector"; hresult = pdisp->GetIDsOfNames(IID_NULL, &szMember, 1, LOCALE_SYSTEM_DEFAULT, &dispid); return 0; } Но при выполнении функции GetIDsOfNames программа вылетает с ошибкой access violation reading location. Правильно ли я понимаю, что у меня в pdisp указатель в никуда? UPDATE Не надо было вызвывать GetInterfacePtr(), так как он возвращает указатель в никуда. немного переделал код теперь он выглядит вот так: #include "stdafx.h" #include "windows.h" #include "Mshtml.h" #include "comutil.h" #import "progid:InternetExplorer.Application" int _tmain(int argc, _TCHAR* argv[]) { CoInitializeEx(NULL, COINIT_APARTMENTTHREADED); bool showIE = true; SHDocVw::IWebBrowser2Ptr ptrIE(_T("InternetExplorer.Application")); ptrIE->Visible = (showIE ? VARIANT_TRUE : VARIANT_FALSE); HRESULT hr = ptrIE->Navigate("myUrl"); if (!SUCCEEDED(hr)) { } int i = 0; // ждем пока загрузится страница по url while (ptrIE->Busy) i++; // получаем html-страницу как DOM (объектная модель документа) IHTMLDocument3 *doc3; hr = ptrIE->Document->QueryInterface(IID_IHTMLDocument3, (void**)&doc3); if FAILED(hr) return(hr); IHTMLElement *parentElem; hr = doc3->getElementById(_com_util::ConvertStringToBSTR("intro-step-4"), &parentElem); if FAILED(hr) return(hr); IDispatch * pDisp; hr = parentElem->get_children(&pDisp); parentElem->Release(); if FAILED(hr) return(hr); IHTMLElementCollection *elemCol; hr = pDisp->QueryInterface(IID_IHTMLElementCollection, (void **)&elemCol); pDisp->Release(); if FAILED(hr) return(hr); _variant_t index = 0; hr = elemCol->item(index, index, &pDisp); if FAILED(hr) return(hr); IHTMLElement * childElem; hr = pDisp->QueryInterface(IID_IHTMLElement, (void **)&childElem); if FAILED(hr) return(hr); BSTR *pszText = new BSTR; hr = childElem->click(); if FAILED(hr) return(hr); hr = childElem->get_innerText(pszText); if FAILED(hr) return(hr); return 0; } Судя по тексту который я получаю в hr = childElem->get_innerText(pszText) я нашел нужный мне элемент. Но метод click() хотя и возвращает S_OK, но клик не производит. По крайней мере никакой реакции в открытом браузере нет. Что делать?
Ответы
Ответ 1
Используйте умные COM-указатели _COM_SMARTPTR_TYPEDEF(IHTMLDocument2, __uuidof(IHTMLDocument2)); _COM_SMARTPTR_TYPEDEF(IHTMLDocument3, __uuidof(IHTMLDocument3)); IDispatchPtr d = ptrIE->Document; IHTMLDocument2Ptr doc2; IHTMLDocument3Ptr doc3; d->QueryInterface(IID_IHTMLDocument2, (void**)&doc2); doc2->... d->QueryInterface(IID_IHTMLDocument3, (void**)&doc3); Я попробовал получить указатель на интерфейс IHtmlSelector (чтобы использовать метод querySelector, но у меня не вышло). У себя я делаю так: if ( SUCCEEDED(doc3->getElementsByTagName(L"HTML", &collection)) ){ long count = 0; if (SUCCEEDED(collection->get_length(&count)) && count ) { IDispatch* disp = 0; VARIANT v; ::VariantInit(&v); v.vt = VT_I4; v.iVal = 0; IElementSelectorPtr selector; collection->item(v, v, &disp); disp->QueryInterface(IID_IElementSelector, (void**)&selector); selector->querySelector(...); } } Но здесь это не работает. Правда IWebBrowserApp считается устаревшим. Используйте IWebBrowser2.
Комментариев нет:
Отправить комментарий