【急】怎样根据iframe的name获取内嵌的iframe的ihtmldocument2?
http://topic.csdn.net/u/20110130/12/d00276b7-058f-4acc-a860-94df73f587cf.html
但是获取到的ihtmldocument2接口再获取ihtmlelement出错~ E_ACCESS_DENIED
3 个解决方案
#1
一般来说是因为IE的安全限制引起的,有两种可能:
1) 你是不是跨线程使用的IHTMLDocument2
如果是这样,最简单的方法是你在线程中再去获取IHTMLDocument2,不要先获取了传到线程中用...
否则就需要列集COM对象
CoMarshalInterThreadInterfaceInStream()/CoGetInterfaceAndReleaseStream()
2) 你的iframe跨域了,为了避免这种情况下的XSS攻击,IE安全限制不允许你跨域操作。
不过跨域的时候在拿IHTMLDocument2应该就会出错。
这个页面上有跨域获取IHTMLDocument2的解决办法:
http://codecentrix.blogspot.com/2007/10/when-ihtmlwindow2getdocument-returns.html
1) 你是不是跨线程使用的IHTMLDocument2
如果是这样,最简单的方法是你在线程中再去获取IHTMLDocument2,不要先获取了传到线程中用...
否则就需要列集COM对象
CoMarshalInterThreadInterfaceInStream()/CoGetInterfaceAndReleaseStream()
2) 你的iframe跨域了,为了避免这种情况下的XSS攻击,IE安全限制不允许你跨域操作。
不过跨域的时候在拿IHTMLDocument2应该就会出错。
这个页面上有跨域获取IHTMLDocument2的解决办法:
http://codecentrix.blogspot.com/2007/10/when-ihtmlwindow2getdocument-returns.html
When IHTMLWindow2::get_document returns E_ACCESSDENIED
Internet Explorer extensions usually needs to access HTML elements. When extensions are initialized they get a IWebBrowser2 pointer representing the browser. Starting with this pointer one can get any HTML element in the web page but to do that we need to browse a hierarchy of frames first. The simplest web pages only have one frame and one document. Web pages containing <frame> or <iframe> have a hierarchy of frames, each frame having its own document.
Here are the objects involved and the corresponding interfaces:
browser - IWebBrowser2
frame/iframe - IHTMLWindow2
document - IHTMLDocument2
element - IHTMLElement
The list bellow shows what method to call to get one object from another:
browser -> document IWebBrowser2::get_Document
document -> frame IHTMLDocument2::get_parentWindow
frame -> document IHTMLWindow2::get_document
frame -> parent frame IHTMLWindow2::get_parent
frame -> children frames IHTMLWindow2::get_frames
A normal call chain to get a HTML element is:
browser -> document -> frame -> child frame -> ... -> child frame -> document -> element
This will work almost all the time. The problems arise when different frames contain documents loaded from different internet domains. In this case IHTMLWindow2::get_document returns E_ACCESSDENIED when trying to get the document from the frame object. I think this happens to prevent cross frame scripting atacks.
Here is HtmlWindowToHtmlDocument function I wrote to be used instead IHTMLWindow2::get_document to bypass the restriction:
// Converts a IHTMLWindow2 object to a IHTMLDocument2. Returns NULL in case of failure.
// It takes into account accessing the DOM across frames loaded from different domains.
CComQIPtr<IHTMLDocument2> HtmlWindowToHtmlDocument(CComQIPtr<IHTMLWindow2> spWindow)
{
ATLASSERT(spWindow != NULL);
CComQIPtr<IHTMLDocument2> spDocument;
HRESULT hRes = spWindow->get_document(&spDocument);
if ((S_OK == hRes) && (spDocument != NULL))
{
// The html document was properly retrieved.
return spDocument;
}
// hRes could be E_ACCESSDENIED that means a security restriction that
// prevents scripting across frames that loads documents from different internet domains.
CComQIPtr<IWebBrowser2> spBrws = HtmlWindowToHtmlWebBrowser(spWindow);
if (spBrws == NULL)
{
return CComQIPtr<IHTMLDocument2>();
}
// Get the document object from the IWebBrowser2 object.
CComQIPtr<IDispatch> spDisp;
hRes = spBrws->get_Document(&spDisp);
spDocument = spDisp;
return spDocument;
}
// Converts a IHTMLWindow2 object to a IWebBrowser2. Returns NULL in case of failure.
CComQIPtr<IWebBrowser2> HtmlWindowToHtmlWebBrowser(CComQIPtr<IHTMLWindow2> spWindow)
{
ATLASSERT(spWindow != NULL);
CComQIPtr<IServiceProvider> spServiceProvider = spWindow;
if (spServiceProvider == NULL)
{
return CComQIPtr<IWebBrowser2>();
}
CComQIPtr<IWebBrowser2> spWebBrws;
HRESULT hRes = spServiceProvider->QueryService(IID_IWebBrowserApp, IID_IWebBrowser2, (void**)&spWebBrws);
if (hRes != S_OK)
{
return CComQIPtr<IWebBrowser2>();
}
return spWebBrws;
}
#2
简单说,跨域要使用IServiceProvider接口!黑白精灵的例子很好
#3
搞定了,谢谢两位!!
祝大家新年快乐
祝大家新年快乐
#1
一般来说是因为IE的安全限制引起的,有两种可能:
1) 你是不是跨线程使用的IHTMLDocument2
如果是这样,最简单的方法是你在线程中再去获取IHTMLDocument2,不要先获取了传到线程中用...
否则就需要列集COM对象
CoMarshalInterThreadInterfaceInStream()/CoGetInterfaceAndReleaseStream()
2) 你的iframe跨域了,为了避免这种情况下的XSS攻击,IE安全限制不允许你跨域操作。
不过跨域的时候在拿IHTMLDocument2应该就会出错。
这个页面上有跨域获取IHTMLDocument2的解决办法:
http://codecentrix.blogspot.com/2007/10/when-ihtmlwindow2getdocument-returns.html
1) 你是不是跨线程使用的IHTMLDocument2
如果是这样,最简单的方法是你在线程中再去获取IHTMLDocument2,不要先获取了传到线程中用...
否则就需要列集COM对象
CoMarshalInterThreadInterfaceInStream()/CoGetInterfaceAndReleaseStream()
2) 你的iframe跨域了,为了避免这种情况下的XSS攻击,IE安全限制不允许你跨域操作。
不过跨域的时候在拿IHTMLDocument2应该就会出错。
这个页面上有跨域获取IHTMLDocument2的解决办法:
http://codecentrix.blogspot.com/2007/10/when-ihtmlwindow2getdocument-returns.html
When IHTMLWindow2::get_document returns E_ACCESSDENIED
Internet Explorer extensions usually needs to access HTML elements. When extensions are initialized they get a IWebBrowser2 pointer representing the browser. Starting with this pointer one can get any HTML element in the web page but to do that we need to browse a hierarchy of frames first. The simplest web pages only have one frame and one document. Web pages containing <frame> or <iframe> have a hierarchy of frames, each frame having its own document.
Here are the objects involved and the corresponding interfaces:
browser - IWebBrowser2
frame/iframe - IHTMLWindow2
document - IHTMLDocument2
element - IHTMLElement
The list bellow shows what method to call to get one object from another:
browser -> document IWebBrowser2::get_Document
document -> frame IHTMLDocument2::get_parentWindow
frame -> document IHTMLWindow2::get_document
frame -> parent frame IHTMLWindow2::get_parent
frame -> children frames IHTMLWindow2::get_frames
A normal call chain to get a HTML element is:
browser -> document -> frame -> child frame -> ... -> child frame -> document -> element
This will work almost all the time. The problems arise when different frames contain documents loaded from different internet domains. In this case IHTMLWindow2::get_document returns E_ACCESSDENIED when trying to get the document from the frame object. I think this happens to prevent cross frame scripting atacks.
Here is HtmlWindowToHtmlDocument function I wrote to be used instead IHTMLWindow2::get_document to bypass the restriction:
// Converts a IHTMLWindow2 object to a IHTMLDocument2. Returns NULL in case of failure.
// It takes into account accessing the DOM across frames loaded from different domains.
CComQIPtr<IHTMLDocument2> HtmlWindowToHtmlDocument(CComQIPtr<IHTMLWindow2> spWindow)
{
ATLASSERT(spWindow != NULL);
CComQIPtr<IHTMLDocument2> spDocument;
HRESULT hRes = spWindow->get_document(&spDocument);
if ((S_OK == hRes) && (spDocument != NULL))
{
// The html document was properly retrieved.
return spDocument;
}
// hRes could be E_ACCESSDENIED that means a security restriction that
// prevents scripting across frames that loads documents from different internet domains.
CComQIPtr<IWebBrowser2> spBrws = HtmlWindowToHtmlWebBrowser(spWindow);
if (spBrws == NULL)
{
return CComQIPtr<IHTMLDocument2>();
}
// Get the document object from the IWebBrowser2 object.
CComQIPtr<IDispatch> spDisp;
hRes = spBrws->get_Document(&spDisp);
spDocument = spDisp;
return spDocument;
}
// Converts a IHTMLWindow2 object to a IWebBrowser2. Returns NULL in case of failure.
CComQIPtr<IWebBrowser2> HtmlWindowToHtmlWebBrowser(CComQIPtr<IHTMLWindow2> spWindow)
{
ATLASSERT(spWindow != NULL);
CComQIPtr<IServiceProvider> spServiceProvider = spWindow;
if (spServiceProvider == NULL)
{
return CComQIPtr<IWebBrowser2>();
}
CComQIPtr<IWebBrowser2> spWebBrws;
HRESULT hRes = spServiceProvider->QueryService(IID_IWebBrowserApp, IID_IWebBrowser2, (void**)&spWebBrws);
if (hRes != S_OK)
{
return CComQIPtr<IWebBrowser2>();
}
return spWebBrws;
}
#2
简单说,跨域要使用IServiceProvider接口!黑白精灵的例子很好
#3
搞定了,谢谢两位!!
祝大家新年快乐
祝大家新年快乐