最近在做一个基于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