написал аддон для IE, который должен вставлять скрипт в страницу, загружаемую на IE.
Вообщем я могу вставить любой текст в страницу, но не могу заставить работать скрипт,
IE просто его игнорирует.
Вот часть кодов:
Здравствуйте, Vicul, Вы писали:
V>написал аддон для IE, который должен вставлять скрипт в страницу, загружаемую на IE. V>Вообщем я могу вставить любой текст в страницу, но не могу заставить работать скрипт, V>IE просто его игнорирует. V>Вот часть кодов:
V>const BSTR g_script =L"<script type=\"text/javascript\" DEFER> alert('foobar');</SCRIPT>";
V>void STDMETHODCALLTYPE CBHOinject::OnDocumentComplete(IDispatch *pDisp, VARIANT *URL) V>{ V> if (m_pMainDisp != pDisp) V> return; V> IHTMLElement* pEl = NULL; V> HRESULT hr; V>........... V> hr = pEl->insertAdjacentHTML(L"afterBegin", g_script); V> if (!SUCCEEDED(hr)) V> {.....// error} V>....... V>}
По-моему, событие OnDocumentComplete вызывается уже после того, как страница была загружена и скрипты отработали. То есть, просто добавлять в текст свой скрипт уже поздно.
Здравствуйте, Vicul, Вы писали:
V>Всем привет,
V>написал аддон для IE, который должен вставлять скрипт в страницу, загружаемую на IE. V>Вообщем я могу вставить любой текст в страницу, но не могу заставить работать скрипт, V>IE просто его игнорирует. V>Вот часть кодов:
V>const BSTR g_script =L"<script type=\"text/javascript\" DEFER> alert('foobar');</SCRIPT>";
Первое, что бросается в глаза — некорректное использование BSTR.
Это не то же самое, что указатель на wchar_t, потому что BSTR хранит длину строки и
вообще с этим типом данных нужно работать через Sys(Re)AllocString/SysFreeString, либо
с помощью ATL-овских оберток CComBSTR.
Лично сталкивался с некоторыми непонятными проблемами, которые сразу же исчезали после
приведения подобных фрагментов с BSTR к правильному виду. Что и Вам настоятельно
советую сделать.
V>void STDMETHODCALLTYPE CBHOinject::OnDocumentComplete(IDispatch *pDisp, VARIANT *URL) V>{ V> if (m_pMainDisp != pDisp) V> return; V> IHTMLElement* pEl = NULL; V> HRESULT hr; V>........... V> hr = pEl->insertAdjacentHTML(L"afterBegin", g_script); V> if (!SUCCEEDED(hr)) V> {.....// error} V>....... V>}
Хм, интересно было бы посмотреть весь код.
На самом деле внедрить элемент <script> на страницу — не такая уж и сложная задача, и
делать это можно по-разному.
Дам подсказку — через указатель на документ нужно создать новый элемент
(IHTMLDocument2::createElement), затем заполнить его атрибуты (IHTMLElement::setAttribute)
соответствующими значениями (type="text/javascript", src="URL" defer="false"), а
затем "прикрепить" этот новый созданный элемент к уже существующему, например, к <body>.
Как добраться до <body> — думаю, задача посильная, см. IHTMLDocument2::get_body и другие.
Еще есть симпатичный способ внедрения скриптов на — в DOM страницы
добавляется функция на Javascript-е, а затем ее тело вызывается через IDispatch::Invoke.
Единственный побочный эффект — имя функции теоретически может оказаться не уникальным.
if(NULL != spHTMLDoc)
{
IHTMLElementCollection* pElColl = NULL;
hr = spHTMLDoc->get_all(&pElColl);
if ( SUCCEEDED(hr))
{
long len = 0;
pElColl->get_length(&len);
if (len)
{
CComBSTR objectTag(L"head");
VARIANT vTag;
vTag.vt = VT_BSTR;
vTag.bstrVal = objectTag;
IHTMLElementCollection *pHeadColl = NULL;
IDispatch* pIDispColl = NULL;
hr = pElColl->tags(vTag, &pIDispColl);
if (!SUCCEEDED(hr))
return;
hr = pIDispColl->QueryInterface(IID_IHTMLElementCollection, (void**) &pHeadColl);
if (!SUCCEEDED(hr))
return;
len = 0;
pHeadColl->get_length(&len);
if (len)
{
VARIANT index;
index.vt = VT_INT;
index.intVal = 0;
IHTMLElement* pEl = NULL;
IDispatch* pdisp = NULL;
hr = pHeadColl->item(index, index, &pDisp);
if (SUCCEEDED(hr))
{
hr = pDisp->QueryInterface(IID_IHTMLElement, (LPVOID*)&pEl);
if (SUCCEEDED(hr))
{
CComBSTR src;
hr = pEl->get_innerHTML(&src);
if(SUCCEEDED(hr))
{
CString str(src.m_str);
len = str.GetLength();
if (len != 0)
{
str.Insert(len, g_script);
// hr = pEl->put_innerHTML(str.AllocSysString());
hr = pEl->insertAdjacentHTML(L"afterBegin", g_script);
if (!SUCCEEDED(hr))
{
switch (hr)
{
case S_OK:
str = L"S_OK";
break;
case S_FALSE:
str = L"S_FALSE";
break;
case E_ABORT:
str = L"E_ABORT";
break;
case E_ACCESSDENIED:
str = L"E_ACCESSDENIED";
break;
case E_FAIL:
str = L"E_FAIL";
break;
case E_HANDLE:
str = L"E_HANDLE";
break;
case E_INVALIDARG:
str = L"E_INVALIDARG";
break;
case E_NOINTERFACE:
str = L"E_NOINTERFACE";
break;
case E_NOTIMPL:
str = L"E_NOTIMPL";
break;
case E_OUTOFMEMORY:
str = L"E_OUTOFMEMORY";
break;
case E_POINTER:
str = L"E_POINTER";
break;
case E_UNEXPECTED:
str = L"E_UNEXPECTED";
break;
default:
str.Format(L"Unknown error: 0x%x", hr);
break;
}
AfxMessageBox(str);
}
}
}
}
}
}
}
}
}
}
}
на концовый switch(hr) не обращай внимание, я его для диагностики влепил
O>Дам подсказку — через указатель на документ нужно создать новый элемент O>(IHTMLDocument2::createElement), затем заполнить его атрибуты (IHTMLElement::setAttribute) O>соответствующими значениями (type="text/javascript", src="URL" defer="false"), а O>затем "прикрепить" этот новый созданный элемент к уже существующему, например, к <body>. O>Как добраться до <body> — думаю, задача посильная, см. IHTMLDocument2::get_body и другие.
вообще то нужно в head (заказчик ну очень хочет, хотя пока достаточно и для боди), за подсказку спасибо, буду пробовать
O>Еще есть симпатичный способ внедрения скриптов на — в DOM страницы O>добавляется функция на Javascript-е, а затем ее тело вызывается через IDispatch::Invoke. O>Единственный побочный эффект — имя функции теоретически может оказаться не уникальным.
Идея интересная, но мне не подойдет, в реале там будет урл-ка, где функции будут меняться
Здравствуйте, Vicul, Вы писали:
V>Всем привет,
V>написал аддон для IE, который должен вставлять скрипт в страницу, загружаемую на IE. V>Вообщем я могу вставить любой текст в страницу, но не могу заставить работать скрипт, V>IE просто его игнорирует. V>Вот часть кодов:
.... V>Любые идеи..
Я как-то выкладывал пример здесь
O>Дам подсказку — через указатель на документ нужно создать новый элемент O>(IHTMLDocument2::createElement), затем заполнить его атрибуты (IHTMLElement::setAttribute) O>соответствующими значениями (type="text/javascript", src="URL" defer="false"), а O>затем "прикрепить" этот новый созданный элемент к уже существующему, например, к <body>. O>Как добраться до <body> — думаю, задача посильная, см. IHTMLDocument2::get_body и другие.