最新文章專題視頻專題問答1問答10問答100問答1000問答2000關(guān)鍵字專題1關(guān)鍵字專題50關(guān)鍵字專題500關(guān)鍵字專題1500TAG最新視頻文章推薦1 推薦3 推薦5 推薦7 推薦9 推薦11 推薦13 推薦15 推薦17 推薦19 推薦21 推薦23 推薦25 推薦27 推薦29 推薦31 推薦33 推薦35 推薦37視頻文章20視頻文章30視頻文章40視頻文章50視頻文章60 視頻文章70視頻文章80視頻文章90視頻文章100視頻文章120視頻文章140 視頻2關(guān)鍵字專題關(guān)鍵字專題tag2tag3文章專題文章專題2文章索引1文章索引2文章索引3文章索引4文章索引5123456789101112131415文章專題3
問答文章1 問答文章501 問答文章1001 問答文章1501 問答文章2001 問答文章2501 問答文章3001 問答文章3501 問答文章4001 問答文章4501 問答文章5001 問答文章5501 問答文章6001 問答文章6501 問答文章7001 問答文章7501 問答文章8001 問答文章8501 問答文章9001 問答文章9501
當(dāng)前位置: 首頁 - 科技 - 知識(shí)百科 - 正文

使用C#處理WebBrowser控件在不同域名中的跨域問題

來源:懂視網(wǎng) 責(zé)編:小采 時(shí)間:2020-11-27 22:42:04
文檔

使用C#處理WebBrowser控件在不同域名中的跨域問題

使用C#處理WebBrowser控件在不同域名中的跨域問題:我們?cè)谧鰓eb測(cè)試時(shí),經(jīng)常會(huì)使用WebBrowser來進(jìn)行一些自動(dòng)化的任務(wù)。而有些網(wǎng)頁上面會(huì)用IFrame去嵌套別的頁面,這些頁面可能不是在相同域名下的,這時(shí)就會(huì)出現(xiàn)跨域問題,無法直接在WebBrowser中獲取到IFrame中的元素。下面來做個(gè)試驗(yàn),自己寫個(gè)頁面嵌套一個(gè)百
推薦度:
導(dǎo)讀使用C#處理WebBrowser控件在不同域名中的跨域問題:我們?cè)谧鰓eb測(cè)試時(shí),經(jīng)常會(huì)使用WebBrowser來進(jìn)行一些自動(dòng)化的任務(wù)。而有些網(wǎng)頁上面會(huì)用IFrame去嵌套別的頁面,這些頁面可能不是在相同域名下的,這時(shí)就會(huì)出現(xiàn)跨域問題,無法直接在WebBrowser中獲取到IFrame中的元素。下面來做個(gè)試驗(yàn),自己寫個(gè)頁面嵌套一個(gè)百

我們?cè)谧鰓eb測(cè)試時(shí),經(jīng)常會(huì)使用WebBrowser來進(jìn)行一些自動(dòng)化的任務(wù)。而有些網(wǎng)頁上面會(huì)用IFrame去嵌套別的頁面,這些頁面可能不是在相同域名下的,這時(shí)就會(huì)出現(xiàn)跨域問題,無法直接在WebBrowser中獲取到IFrame中的元素。下面來做個(gè)試驗(yàn),自己寫個(gè)頁面嵌套一個(gè)百度的首頁,然后在我們自己的頁面上輸入要查詢的詞,最后在百度上自動(dòng)完成搜索。
代碼如下:
<!DOCTYPE html>
<html lang="en" xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta charset="utf-8" />
<title></title>
</head>
<body>
<iframe id="baidu" style="float:left;" width="500" height="500" src="http://www.baidu.com"></iframe>
<div>
測(cè)試值:<input id="search" type="text" />
</div>
</body>
</html>

下面再建一個(gè)簡(jiǎn)單的WinForm工程測(cè)試一下,界面如下:

下面就是WebBrowser的測(cè)試代碼:
代碼如下:
using System;
using System.Windows.Forms;
namespace WebBrowserTest
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
this.webBrowser1.Navigate(this.textBox1.Text);
}
private void button2_Click(object sender, EventArgs e)
{
var doc = this.webBrowser1.Document;
var frames = doc.Window.Frames;
String testValue = doc.GetElementById("search").GetAttribute("value");
frames[0].Document.GetElementById("kw").SetAttribute("value", testValue);
frames[0].Document.GetElementById("su").InvokeMember("click");
}
}
}

我們運(yùn)行我們的測(cè)試程序后,加載之前我們自己寫的頁面后,在自己的頁面上輸入我們要查詢的詞,點(diǎn)擊測(cè)試按鈕,就會(huì)看到程序報(bào)未處理 UnauthorizedAccessException錯(cuò)誤:
下面來編寫一個(gè)Helper類來解決這個(gè)問題,主要原理大致就是利用IWebBrowser2這個(gè)接口來獲取Ifream中的Dom,IWebBrowser2中的document可以轉(zhuǎn)換為IHtmlDocument1,IHtmlDocument2,IHtmlDocument3。
代碼如下:
using System;
using System.Runtime.InteropServices;
using System.Windows.Forms;
using mshtml;
namespace WebBrowserTest
{
// 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);
}
public enum OLECMDF
{
OLECMDF_DEFHIDEONCTXTMENU = 0x20,
OLECMDF_ENABLED = 2,
OLECMDF_INVISIBLE = 0x10,
OLECMDF_LATCHED = 4,
OLECMDF_NINCHED = 8,
OLECMDF_SUPPORTED = 1
}
public enum OLECMDID
{
OLECMDID_PAGESETUP = 8,
OLECMDID_PRINT = 6,
OLECMDID_PRINTPREVIEW = 7,
OLECMDID_PROPERTIES = 10,
OLECMDID_SAVEAS = 4
}
public enum OLECMDEXECOPT
{
OLECMDEXECOPT_DODEFAULT,
OLECMDEXECOPT_PROMPTUSER,
OLECMDEXECOPT_DONTPROMPTUSER,
OLECMDEXECOPT_SHOWHELP
}
[ComImport, Guid("D30C1661-CDAF-11d0-8A3E-00C04FC9E26E"), TypeLibType(TypeLibTypeFlags.FOleAutomation | TypeLibTypeFlags.FDual | TypeLibTypeFlags.FHidden)]
public interface IWebBrowser2
{
[DispId(100)]
void GoBack();
[DispId(0x65)]
void GoForward();
[DispId(0x66)]
void GoHome();
[DispId(0x67)]
void GoSearch();
[DispId(0x68)]
void Navigate([In] string Url, [In] ref object flags, [In] ref object targetFrameName, [In] ref object postData, [In] ref object headers);
[DispId(-550)]
void Refresh();
[DispId(0x69)]
void Refresh2([In] ref object level);
[DispId(0x6a)]
void Stop();
[DispId(200)]
object Application { [return: MarshalAs(UnmanagedType.IDispatch)] get; }
[DispId(0xc9)]
object Parent { [return: MarshalAs(UnmanagedType.IDispatch)] get; }
[DispId(0xca)]
object Container { [return: MarshalAs(UnmanagedType.IDispatch)] get; }
[DispId(0xcb)]
object Document { [return: MarshalAs(UnmanagedType.IDispatch)] get; }
[DispId(0xcc)]
bool TopLevelContainer { get; }
[DispId(0xcd)]
string Type { get; }
[DispId(0xce)]
int Left { get; set; }
[DispId(0xcf)]
int Top { get; set; }
[DispId(0xd0)]
int Width { get; set; }
[DispId(0xd1)]
int Height { get; set; }
[DispId(210)]
string LocationName { get; }
[DispId(0xd3)]
string LocationURL { get; }
[DispId(0xd4)]
bool Busy { get; }
[DispId(300)]
void Quit();
[DispId(0x12d)]
void ClientToWindow(out int pcx, out int pcy);
[DispId(0x12e)]
void PutProperty([In] string property, [In] object vtValue);
[DispId(0x12f)]
object GetProperty([In] string property);
[DispId(0)]
string Name { get; }
[DispId(-515)]
int HWND { get; }
[DispId(400)]
string FullName { get; }
[DispId(0x191)]
string Path { get; }
[DispId(0x192)]
bool Visible { get; set; }
[DispId(0x193)]
bool StatusBar { get; set; }
[DispId(0x194)]
string StatusText { get; set; }
[DispId(0x195)]
int ToolBar { get; set; }
[DispId(0x196)]
bool MenuBar { get; set; }
[DispId(0x197)]
bool FullScreen { get; set; }
[DispId(500)]
void Navigate2([In] ref object URL, [In] ref object flags, [In] ref object targetFrameName, [In] ref object postData, [In] ref object headers);
[DispId(0x1f5)]
OLECMDF QueryStatusWB([In] OLECMDID cmdID);
[DispId(0x1f6)]
void ExecWB([In] OLECMDID cmdID, [In] OLECMDEXECOPT cmdexecopt, ref object pvaIn, IntPtr pvaOut);
[DispId(0x1f7)]
void ShowBrowserBar([In] ref object pvaClsid, [In] ref object pvarShow, [In] ref object pvarSize);
[DispId(-525)]
WebBrowserReadyState ReadyState { get; }
[DispId(550)]
bool Offline { get; set; }
[DispId(0x227)]
bool Silent { get; set; }
[DispId(0x228)]
bool RegisterAsBrowser { get; set; }
[DispId(0x229)]
bool RegisterAsDropTarget { get; set; }
[DispId(0x22a)]
bool TheaterMode { get; set; }
[DispId(0x22b)]
bool AddressBar { get; set; }
[DispId(0x22c)]
bool Resizable { get; set; }
}
class CorssDomainHelper
{
private static Guid IID_IWebBrowserApp = new Guid("0002DF05-0000-0000-C000-000000000046");
private static Guid IID_IWebBrowser2 = new Guid("D30C1661-CDAF-11D0-8A3E-00C04FC9E26E");
// Utility for IE cross domain access
// Returns null in case of failure.
public static IHTMLDocument3 GetDocumentFromWindow(IHTMLWindow2 htmlWindow)
{
if (htmlWindow == null)
{
return null;
}
// First try the usual way to get the document.
try
{
IHTMLDocument2 doc = htmlWindow.document;
return (IHTMLDocument3)doc;
}
catch (COMException comEx)
{
// I think COMException won't be ever fired but just to be sure ...
}
catch (UnauthorizedAccessException)
{
}
catch (Exception ex)
{
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.
IWebBrowser2 browser = (IWebBrowser2)(brws);
return (IHTMLDocument3)browser.Document;
}
catch (Exception ex)
{
Console.WriteLine(ex);
}
return null;
}
}
}

最后將我們的運(yùn)行代碼改為如下形式,調(diào)用Helper類中的GetDocumentFromWindow方法:
代碼如下:
using System;
using System.Windows.Forms;
using mshtml;
namespace WebBrowserTest
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
this.webBrowser1.Navigate(this.textBox1.Text);
}
private void button2_Click(object sender, EventArgs e)
{
var doc = this.webBrowser1.Document;
var frames = doc.Window.Frames;
String testValue = doc.GetElementById("search").GetAttribute("value");
IHTMLDocument3 baiduDoc = CorssDomainHelper.GetDocumentFromWindow(frames[0].DomWindow as IHTMLWindow2);
baiduDoc.getElementById("kw").setAttribute("value", testValue);
baiduDoc.getElementById("su").click();
}
}
}

最后運(yùn)行一下程序可以看到我們可以正常獲取到百度上的元素了。

補(bǔ)充一下路過秋天說的問題:
其實(shí)關(guān)于這些接口其實(shí)我也沒有很深入的研究過,不過網(wǎng)上倒是能搜到很多相關(guān)資料介紹這些接口的不同,我這里給一個(gè)鏈接:
http://hi.baidu.com/christole/item/1c8dfd1a791a53643f87ced8
然后關(guān)于我上面的代碼為什么要使用IHMLDocument3,而不是其它兩個(gè)接口,因?yàn)镮HMLDocument3這個(gè)接口里面定義了我需要的getElementById這個(gè)方法。
通過查看MSDN,你可以找到你需要的屬性或者方法,然后直接在代碼里面轉(zhuǎn)換為你需要的類型使用就可以了,它們之間都是可以互相轉(zhuǎn)化的。比如上面我用完了getElementById方法,我需要查看網(wǎng)頁的title,那么可以將我上面的baiduDoc變量強(qiáng)制轉(zhuǎn)為IHMLDocument2,然后就可以直接使用它的title屬性了。
參考鏈接:
http://msdn.microsoft.com/en-us/library/aa752052(v=vs.85).aspx
http://codecentrix.blogspot.com/2007/10/when-ihtmlwindow2getdocument-returns.html
http://msdn.microsoft.com/en-us/library/aa752641(v=VS.85).aspx

聲明:本網(wǎng)頁內(nèi)容旨在傳播知識(shí),若有侵權(quán)等問題請(qǐng)及時(shí)與本網(wǎng)聯(lián)系,我們將在第一時(shí)間刪除處理。TEL:177 7030 7066 E-MAIL:11247931@qq.com

文檔

使用C#處理WebBrowser控件在不同域名中的跨域問題

使用C#處理WebBrowser控件在不同域名中的跨域問題:我們?cè)谧鰓eb測(cè)試時(shí),經(jīng)常會(huì)使用WebBrowser來進(jìn)行一些自動(dòng)化的任務(wù)。而有些網(wǎng)頁上面會(huì)用IFrame去嵌套別的頁面,這些頁面可能不是在相同域名下的,這時(shí)就會(huì)出現(xiàn)跨域問題,無法直接在WebBrowser中獲取到IFrame中的元素。下面來做個(gè)試驗(yàn),自己寫個(gè)頁面嵌套一個(gè)百
推薦度:
標(biāo)簽: 域名 跨域問題 跨域問
  • 熱門焦點(diǎn)

最新推薦

猜你喜歡

熱門推薦

專題
Top