清泛IT社区

标题: 如何获取IE (控件)的所有链接(包括Frameset, iframe) [打印本页]

作者: 清泛网    时间: 2015-11-11 10:48
标题: 如何获取IE (控件)的所有链接(包括Frameset, iframe)
来源:新浪博客

IE 顶层 body 节点通过IHTMLElement->get_all 方法无法获取iframe 里面的节点列表:
  1. CComPtr<IHTMLElement> body;
  2. ...
  3. CComPtr<IDispatch> spDispCollection;
  4. body->get_all(&spDispCollection);
复制代码
所以要获取iframe/frame(frameset) 里面的节点列表的话, 则需要根据body/doc 找到frames, 然后从frames -> IHTMLWindow2 -> IHTMLDocument2 . 主要有2个方法, 下面是代码片段
方法一:
  1. IHTMLDocument2 *pDoc = 浏览器的Document(IWebBrowser2->IDispatch->IHTMLDocument2);
  2. IHTMLWindow2 *pHTMLWnd = NULL;
  3. IHTMLDocument2 *pFrameDoc=NULL;
  4. IHTMLFramesCollection2 *pFramesCollection=NULL;
  5. LPDISPATCH lpDispatch;

  6. long p;
  7. VARIANT varindex,varresult;
  8. varresult.vt=VT_DISPATCH;
  9. varindex.vt = VT_I4;
  10. if(pDoc!=NULL)
  11. {
  12.      HRESULT hr=pDoc->get_frames(&pFramesCollection);
  13.     if(SUCCEEDED(hr)&&pFramesCollection!=NULL)
  14.      {
  15.          hr=pFramesCollection->get_length(&p);
  16.         if(SUCCEEDED(hr))
  17.             for(int i=0; i<p; i++)
  18.              {
  19.                  varindex.lVal = i;
  20.                 if(pFramesCollection->item(&varindex, &varresult) ==S_OK)
  21.                  {
  22.                      lpDispatch=(LPDISPATCH)varresult.ppdispVal;
  23.                     if (SUCCEEDED(lpDispatch->QueryInterface(IID_IHTMLWindow2, (LPVOID *)&pHTMLWnd)))
  24.                      {
  25.                         if(SUCCEEDED(pHTMLWnd->get_document( &pFrameDoc)))
  26.                          {
  27.                             //work with the pFrameDoc获取IE (控件)的所有链接(包括Frameset, iframe) - . - Welcome to the hell
  28.                          }
  29.                          pHTMLWnd->Release();
  30.                          pHTMLWnd=NULL;
  31.                      }
  32.                  }
  33.              }
  34.              pFramesCollection->Release();
  35.      }
  36.      pDoc->Release();
  37. }
复制代码
方法二:
  1. CComQIPtr<IHTMLElement> pElem = ; // 可以递归上面的 CComPtr<IDispatch> spDispCollectio 来得到
  2. CComBSTR bstrTagName;
  3. pElem->get_tagName(&bstrTagName);
  4. if ( lstrcmpiW(L"IFRAME", bstrTagName)==0 ||
  5.          lstrcmpiW(L"FRAME", bstrTagName)==0 )
  6. {
  7.      CComQIPtr<IHTMLFrameBase2>     _framebase2;
  8.      CComPtr<IHTMLWindow2>         _framewindow;
  9.      CComPtr<IHTMLDocument2>         _framedoc;
  10.    
  11.     if( (_framebase2 = spItem)
  12.         && SUCCEEDED( _framebase2->get_contentWindow(&_framewindow) ) && _framewindow!=NULL
  13.         && SUCCEEDED( _framewindow->get_document(&_framedoc) ) && _framedoc!=NULL )
  14.      {
  15.         // 对 _framedoc 节点进行处理
  16.      }
  17. }
复制代码
iframe 跨域访问(cross frame)   zz from : http://codecentrix.blogspot.com/ ... cument-returns.html
由于安全性限制, 为防止跨域脚本攻击, 当frames 跨域的时候, IHTMLWindow2::get_document 调用将返回 E_ACCESSDENIED .
下面函数 HtmlWindowToHtmlDocument 对于跨域的frame 通过 IHTMLWindow2 -> IID_IWebBrowserApp -> IHTMLWindow2 绕过了限制。
  1. // Converts a IHTMLWindow2 object to a IHTMLDocument2. Returns NULL in case of failure.
  2. // It takes into account accessing the DOM across frames loaded from different domains.
  3. CComQIPtr<IHTMLDocument2> HtmlWindowToHtmlDocument(CComQIPtr<IHTMLWindow2> spWindow)
  4. {
  5.       ATLASSERT(spWindow != NULL);

  6.       CComQIPtr<IHTMLDocument2> spDocument;
  7.       HRESULT hRes = spWindow->get_document(&spDocument);
  8.    
  9.      if ((S_OK == hRes) && (spDocument != NULL))
  10.       {
  11.           // The html document was properly retrieved.
  12.           return spDocument;
  13.       }

  14.      // hRes could be E_ACCESSDENIED that means a security restriction that
  15.      // prevents scripting across frames that loads documents from different internet domains.
  16.       CComQIPtr<IWebBrowser2>   spBrws = HtmlWindowToHtmlWebBrowser(spWindow);
  17.      if (spBrws == NULL)
  18.       {
  19.           return CComQIPtr<IHTMLDocument2>();
  20.       }

  21.      // Get the document object from the IWebBrowser2 object.
  22.       CComQIPtr<IDispatch> spDisp;
  23.       hRes = spBrws->get_Document(&spDisp);
  24.       spDocument = spDisp;

  25.      return spDocument;
  26. }


  27. // Converts a IHTMLWindow2 object to a IWebBrowser2. Returns NULL in case of failure.
  28. CComQIPtr<IWebBrowser2> HtmlWindowToHtmlWebBrowser(CComQIPtr<IHTMLWindow2> spWindow)
  29. {
  30.       ATLASSERT(spWindow != NULL);

  31.       CComQIPtr<IServiceProvider>   spServiceProvider = spWindow;
  32.      if (spServiceProvider == NULL)
  33.       {
  34.           return CComQIPtr<IWebBrowser2>();
  35.       }

  36.       CComQIPtr<IWebBrowser2> spWebBrws;
  37.       HRESULT hRes = spServiceProvider->QueryService(IID_IWebBrowserApp, IID_IWebBrowser2, (void**)&spWebBrws);
  38.      if (hRes != S_OK)
  39.       {
  40.           return CComQIPtr<IWebBrowser2>();
  41.       }

  42.      return spWebBrws;
  43. }
复制代码






欢迎光临 清泛IT社区 (https://bbs.tsingfun.com/) Powered by Discuz! X3.3