Open a page using webbrowser, and there is an IFRAME in the page. When the page is fully opened in webbrowser, The system. unauthorizedaccessexception exception is always thrown when obtaining the IFRAME.
Console.WriteLine(this.webMain.Document.Window.Frames[0].Url);
"This. webmain. Document. Window. Frames [0]. url" raises an exception of the "system. unauthorizedaccessexception" type.
Base {system. systemexception }:{ "Access denied. (Exception from hresult: 0x80070005 (e_accessdenied ))"}
Recently, this cross-domain security problem has been plagued. After a long time, I finally found a C ++ method htmlwindowtohtmlwebbrowser with the help of my friends.
CComPtr<IWebBrowser2> CTimerSerachDlg::HtmlWindowToHtmlWebBrowser(CComPtr<IHTMLWindow2> spWindow) { ATLASSERT(spWindow != NULL); CComQIPtr<IServiceProvider> spServiceProvider = spWindow; if (spServiceProvider == NULL) { return CComPtr<IWebBrowser2>(); } CComPtr<IWebBrowser2> spWebBrws; HRESULT hRes = spServiceProvider->QueryService(IID_IWebBrowserApp, IID_IWebBrowser2, (void**)&spWebBrws); if (hRes != S_OK) { return CComPtr<IWebBrowser2>(); } return spWebBrws; } // 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. CComPtr<IHTMLDocument2> CTimerSerachDlg::HtmlWindowToHtmlDocument(CComPtr<IHTMLWindow2> spWindow) { ATLASSERT(spWindow != NULL); CComPtr<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. CComPtr<IWebBrowser2> spBrws = HtmlWindowToHtmlWebBrowser(spWindow); if (spBrws == NULL) { return CComPtr<IHTMLDocument2>(); } // Get the document object from the IWebBrowser2 object. CComPtr<IDispatch> spDisp; hRes = spBrws->get_Document(&spDisp); spDocument = spDisp; return spDocument; }
Later I found the author's blog, but it blocked the Blogspot in China and could not be accessed directly.
Then I found another article by the author: http://codecentrix.blogspot.com/2008/02/when-ihtmlwindow2document-throws.html
C # Cross-origin access IFRAME: http://www.codecentrix.com/blog/wnd2doc_csharp/GetDocumentFromWindowCsharp.zip
mshtml.HTMLDocumentClass htmlDoc = this.webMain.Document.DomDocument as mshtml.HTMLDocumentClass; object index = 0; mshtml.IHTMLWindow2 frameWindow = htmlDoc.frames.item(ref index) as mshtml.IHTMLWindow2; Console.WriteLine( CodecentrixSample.CrossFrameIE.GetDocumentFromWindow(frameWindow).activeElement.innerHTML);
Code for Interface Conversion:
using System;using System.Runtime.InteropServices;using mshtml;namespace CodecentrixSample{ public class CrossFrameIE { // Returns null in case of failure. public static IHTMLDocument2 GetDocumentFromWindow(IHTMLWindow2 htmlWindow) { if (htmlWindow == null) { return null; } // 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 to be sure ... if (comEx.ErrorCode != E_ACCESSDENIED) { return null; } } catch (System.UnauthorizedAccessException) { } catch { // Any other error. return null; } // At this point the error was E_ACCESSDENIED because the frame contains a document from another domain. // IE tries to prevent a cross frame scripting security issue. try { // Convert IHTMLWindow2 to IWebBrowser2 using IServiceProvider. IServiceProvider sp = (IServiceProvider)htmlWindow; // Use IServiceProvider.QueryService to get IWebBrowser2 object. Object brws = null; sp.QueryService(ref IID_IWebBrowserApp, ref IID_IWebBrowser2, out brws); // Get the document from IWebBrowser2. SHDocVw.IWebBrowser2 browser = (SHDocVw.IWebBrowser2)(brws); return (IHTMLDocument2)browser.Document; } catch { } return null; } private const int E_ACCESSDENIED = unchecked((int)0x80070005L); private static Guid IID_IWebBrowserApp = new Guid("0002DF05-0000-0000-C000-000000000046"); private static Guid IID_IWebBrowser2 = new Guid("D30C1661-CDAF-11D0-8A3E-00C04FC9E26E"); } // This is the COM IServiceProvider interface, not System.IServiceProvider .Net interface! [ComImport(), ComVisible(true), Guid("6D5140C1-7436-11CE-8034-00AA006009FA"), InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)] public interface IServiceProvider { [return: MarshalAs(UnmanagedType.I4)][PreserveSig] int QueryService(ref Guid guidService, ref Guid riid, [MarshalAs(UnmanagedType.Interface)] out object ppvObject); }}