C# webbrowser 控件跨域访问frame异常问解决方案

作者: admin 日期: 2015-06-29 18:21:44 人气: - 评论: 0

最近在做一个基于C# webbrowser的程序,功能很简单打开网站随便浏览几个文章,然后打开广告的网站再随便点击几下,原来以为很简单的一个程序,实际操作的时候缺遇到了问题。

现在的广告联盟代码一般都是用frame的方式加载的要获得广告联盟代码里面的链接就要进行页面内的frame操作,很自然的想到了用

webBrowser1.Document.Window.Frames

来操作自己写了个页面测试成功,一轮到广告联盟的页面就提示出现异常:

异常来自 HRESULT:0x80070005 (E_ACCESSDENIED))"UnauthorizedAccessException

百度了下总算解决了,解决过程如下

1、下载GetDocumentFromWindowCsharp.zip这个代码编译之后会有个dll文件Interop.SHDocVw.dll

2、在项目中添加一个类,代码如下

// FREE code from CODECENTRIX

// http://www.codecentrix.com/

// http://codecentrix.blogspot.com/

using System;

using System.Runtime.InteropServices;

using mshtml;

 

 

namespace CodecentrixSample

{

    publicclassCrossFrameIE

    {

        //Returns null in case of failure.

        publicstaticIHTMLDocument2 GetDocumentFromWindow(IHTMLWindow2htmlWindow)

        {

            if(htmlWindow == null)

            {

               returnnull;

            }

 

            //First try the usual way to get the document.

            try

            {

               IHTMLDocument2 doc = htmlWindow.document;

               return doc;

            }

            catch(COMException comEx)

            {

               // I think COMException won't be ever fired but just tobe sure ...

               if (comEx.ErrorCode != E_ACCESSDENIED)

               {

                   returnnull;

               }

            }

            catch(System.UnauthorizedAccessException)

            {

            }

            catch

            {

               // Any other error.

               returnnull;

            }

 

            //At this point the error was E_ACCESSDENIED because the frame contains adocument from another domain.

            //IE tries to prevent a cross frame scripting security issue.

            try

            {

               // Convert IHTMLWindow2 to IWebBrowser2 usingIServiceProvider.

               IServiceProvider sp = (IServiceProvider)htmlWindow;

 

               // UseIServiceProvider.QueryService to get IWebBrowser2 object.

               Object brws = null;

               sp.QueryService(refIID_IWebBrowserApp, ref IID_IWebBrowser2, outbrws);

 

               // Get the document from IWebBrowser2.

                SHDocVw.IWebBrowser2browser = (SHDocVw.IWebBrowser2)(brws);

 

               return (IHTMLDocument2)browser.Document;

            }

            catch

            {

            }

 

            returnnull;

        }

 

        privateconstint  E_ACCESSDENIED      = unchecked((int)0x80070005L);

        privatestaticGuid IID_IWebBrowserApp = newGuid("0002DF05-0000-0000-C000-000000000046");

        privatestaticGuid IID_IWebBrowser2  = newGuid("D30C1661-CDAF-11D0-8A3E-00C04FC9E26E");

    }

 

    //This is the COM IServiceProvider interface, not System.IServiceProvider .Netinterface!

    [ComImport(), ComVisible(true),Guid("6D5140C1-7436-11CE-8034-00AA006009FA"),

    InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)]

    publicinterfaceIServiceProvider

    {

                       [return: MarshalAs(UnmanagedType.I4)][PreserveSig]

                       intQueryService(refGuidguidService, refGuidriid, [MarshalAs(UnmanagedType.Interface)]outobjectppvObject);

    }

}



3 引用Interop.SHDocVw.dll和Microsoft.mshtml.dll


4 下面是我调用的例子

               HTMLDocumentClass htmlDoc= (HTMLDocumentClass)webBrowser1.Document.DomDocument;

               for (inti = 0; i < htmlDoc.frames.length; i++)

               {

                   object index = i;

                   IHTMLWindow2 frameWindow = (IHTMLWindow2)htmlDoc.frames.item(refindex);

                   int l = CodecentrixSample.CrossFrameIE.GetDocumentFromWindow(frameWindow).links.length;

                   for (intj = 0; j < l; j++)

                   {

 

                        IHTMLElement HE = (IHTMLElement)CodecentrixSample.CrossFrameIE.GetDocumentFromWindow(frameWindow).links.item(j);

                        stringthisurl=HE.getAttribute("href").ToString();

                        if(thisurl.IndexOf(url) != -1)

                       {

                           localurls.Add(thisurl);

                        }

                        else

                        {

                            if(thisurl.Length > 10 && thisurl.IndexOf("baidu")== -1 && thisurl.IndexOf("sogou")== -1)

                            {

                               otherlurls.Add(thisurl);

                            }

                        }

 

                   }

                }

5、 代码下载地址: http://www.codestorm.cn/webftp/data/nfs//B/Code/GetDocumentFromWindowCsharp.zip

相关内容

发表评论
更多 网友评论0 条评论)
暂无评论

Copyright © 2012-2014 我的代码板 Inc. 保留所有权利。

页面耗时0.0255秒, 内存占用1.84 MB, 访问数据库10次

闽ICP备15009223号-1