C#开发中WebBrowser控件的跨域问题使用实例

而有些网页上面会用IFrame去嵌套别的页面,这些页面可能不是在相同域名下的,这时就
【菜科解读】
我们在做web测试时,经常会使用WebBrowser来进行一些自动化的任务。
而有些网页上面会用IFrame去嵌套别的页面,这些页面可能不是在相同域名下的,这时就会出现跨域问题,无法直接在WebBrowser中获取到IFrame中的元素。
下面来做个试验,自己写个页面嵌套一个百度的首页,然后在我们自己的页面上输入要查询的词,最后在百度上自动完成搜索。
下面再建一个简单的WinForm工程测试一下,界面如下:
下面就是WebBrowser的测试代码:
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"); } }}
我们运行我们的测试程序后,加载之前我们自己写的页面后,在自己的页面上输入我们要查询的词,点击测试按钮,就会看到程序报未处理UnauthorizedAccessException错误:
下面来编写一个Helper类来解决这个问题,主要原理大致就是利用IWebBrowser2这个接口来获取Ifream中的Dom,IWebBrowser2中的document可以转换为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; } }}
最后将我们的运行代码改为如下形式,调用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(); } }}
最后运行一下程序可以看到我们可以正常获取到百度上的元素了。
开发,中,WebBrowser,控件,的,跨域,问题,使用,昭陵六骏中,为什么这匹马排首位?
“昭陵六骏”,是指唐太宗李世民的昭陵祭坛前,东西两侧六块骏马青石浮雕。
在千古帝王中,李世民对自己的战功是很自负的,毛主席也称赞他为“最能打仗的帝王”。
为了自诩驰骋疆场骑射的生活,他在修建自己陵墓时,就命工艺家阎立德和画家,用青石凿刻了生前骑过的六匹战马的浮雕,以歌颂自己南征北战的武功。
它们既象征唐太宗所经历的最主要六大战役,同时也是表彰他在唐王朝创建过程中立下的赫赫战功。
六骏中,排在东侧的是特勒骠(tè lè biāo)、青骓(qīng zhuī)、什伐赤;排在西侧的是飒露紫、拳毛騧(quán máo guā)、白蹄乌。
六骏中,排在东西两侧首位的为何是特勒骠和飒露紫呢,而特勒骠更是位居六骏之首? 先说东侧第二骏青骓。
这是一匹苍白杂色骏马,为李世民平定窦建德时所乘。
此马快如闪电,虎牢关战役中,李世民骑上青骓马,亲率精锐骑兵直入敌阵20余里,打跨窦建德十几万大军。
一场大战下来,青骓身中五箭(前边一箭,后面四箭),都是迎面射来的,足见它奔跑起来迅猛异常。
虎牢关大捷,是唐王朝统一战争中一场决定性的胜利。
东侧第三骏什伐赤,这是一匹来自西域的汗血宝马,是李世民在洛阳虎牢关与王世充、窦建德作战时的又一匹坐骑。
石刻上的什伐赤马,凌空飞奔,身中五箭,都在马的臀部。
再说西侧第二骏拳毛騧(quán máo guā),这个名字很难读。
拳毛騧,为李世民平定刘黑闼时的坐骑。
石刻上的拳毛騧身中9箭,是六骏里中箭最多的,也说明战斗很激烈。
这场战争结束后,唐王朝统一中国的大业便宣告完成了。
西侧第三骏是白蹄乌。
这是一匹纯黑色、四蹄俱白的骏马,为李世民平定薛仁杲时所乘。
在争夺关中时,李世民骑着白蹄乌身先士卒,一昼夜奔驰200余里,迫使薛仁杲投降。
位于西侧首位的则是飒露紫。
它是李世民东征洛阳,铲平王世充势力时的坐骑,前胸中一箭。
与其它五骏不同的是,六骏中惟这件作品附刻人物。
作品中,牵着战马正在拨箭的人叫丘行恭。
在洛阳邙山一战中,骑着飒露紫的李世民杀得性起,却与后方失去联系,被敌人团团包围。
敌兵一箭射中“飒露紫”前胸。
危急关头,丘行恭赶到,回身张弓四剑,逼退敌人。
然后,丘行恭跳下马来,给飒露紫拨箭,并且把自己的坐骑让给李世民,两人突围而归。
李世民为了表彰丘行恭拼死护驾的战功,特命将拔箭的情形刻于石屏上。
所以,“飒露紫”既有表现李世民一生战功的含意,还有树立军人楷模的内涵,用意更为深刻,从而置于西侧之首。
而位于东侧首位的特勒骠,为李世民平定宋金刚时所乘坐骑。
李世民骑着“特勒骠”,曾一昼夜间急追二百多里地,交战数十回合,连打八次硬仗,立下功绩。
这次追歼中,李世民一连两天水米未进,三天人没解甲,马没卸鞍。
李世民也凭借这一役,收复大唐王业发祥地——太原和河东失地。
因为作战的时候,此马凭借卓越的奔跑能力和罕见的勇气,七次令李世民化险为夷。
这也成为他位居六骏之首的重要原因。
从昭陵六骏的浮雕内容来看,特勒骠是六骏中除白蹄乌外唯一没有中箭的。
从所立功勋和战役的重要性来看,特勒骠位居六骏之首,也就不难理解了。
昭陵六骏,是极为珍贵的国宝级文物。
可惜,其中的两骏“飒露紫”和“拳毛騧”,被我国的古董商卢芹斋,于1914年以12.5万美元价格卖给了一个叫毕士博的美国人,现存费城宾夕法尼亚大学博物馆。
过了4年,毕士博又来图谋另外4尊浮雕时,被自发的中国百姓阻拦,“四骏”因此留在了国内,现为西安碑林博物馆收藏。
随机文章魔克拉-姆边贝图片曝光,出没沼泽专杀河马(专家称是大象被误认)揭秘现在还存活着美人鱼吗,美国海军抓到活体美人鱼秘密研究揭秘蜜蜂的飞行之谜,高频振翅达到快速飞行的目的(每秒240次)人的长相是前世修来的,前世修善果长相甜美/作恶则长相丑陋外星人养殖人类吃灵魂,传人类是外星在地球培养的食物(无根据)
如何在word中设置数字的千位分隔符?两种方法轻松搞定
WORD实现不了你的欲望。
不过你可以在Excel中输入这样的数据,“复制”后,到WORD中“编辑”/“选择性粘贴”/“无款式文本”即可。
在Excel中输入这样的数据的法子是: 选中将要输入的单元格区域,右击该区域,在弹出的快捷菜单中选择“设置单元格款式”/“数字”/“货币”,将对话框中的货币款式选为:“无”,负数款式选为:“-1,234”,“肯定”即可。
不过今天西西教您用Word必备工具箱帮您实现这个功能:前一段时间给大家介绍了用手工方法给word中的数据添加千位分割符,比如:76,656.251351,为了更加方便,本人特地制作了这个功能,实现一键操作,还不赶紧试一试。
动画演示:自动给word文档里的数据设置“千位分隔符”去除当前文档中数值的千位分隔符(就是数值中的那个小逗号)动画演示:word必备工具箱--去除千位分隔符功能巧给word文档里的数据设置“千位分隔符”高级版我们在word文档中会写很多数据,有些带小数点,有些不带,但为了直观,需要把这些数据全部设置为“千位分隔符”的格式,如:100000.00元,转换为100,000.00元(每3位数加一个英文半角逗号)。
手工添加,既费时费力,效率低,还会出错;用编制宏代码的方法,又不易学会。
有没有一种简单的方法在数据里设置千位分隔符呢?答案是肯定的。
在实际工作中,通过“全部替换”按钮,就能完成整篇文档财务数据千位分隔符的添加,并且年份数字不受影响。
具体方法如下:(1)用CTRL+H快捷键,或者点击菜单或按钮:2007以下版本,点击word中的“编辑”菜单,在下拉菜单中点“替换”,出现“查找和替换”对话框。
2007及以上版本,则在功能区点击“编辑”按钮,再点击"替换",如图:(2)2007以下版本,点“高级”按钮;2007及以上版本,点“更多”按钮,勾选“使用通配符”复选框。
(3)“查找内容”中填入: ([0-9])([0-9]{3})([!][0-9年]),“替换”中填入:\1,\2\3注意:查找内容:([0-9])([0-9]{3})([!][0-9年])和替换为: \1,\2\3是固定不变的,在输入法为英文半角的状态输入。
(4)执行“全部替换”。
重复按“全部替换”按钮,直到提示“替换0处”为止。
查找框中“([0-9])([0-9]{3})([!][0-9年])”的含义是:()[ ]{ }称为:通配符。
( ) 表达式,[ ] 范围内的任意单个字符,{ } 指定前一范围次数(勾选 “使用通配符”复选框让通配符设定的条件起作用)。
意思是:查找不是0-9或者“年”之前的三位以上的数字(WORD默认从左到右顺序查找)。
替换框中“\1,\2\3”的含义是:\1代表查找框中第一个表达式,\2代表查找框中第二个表达式,以此类推。
意思是:按从左到右的顺序,在不是0-9或者“年”前的第四位数字后加千分位符(,)。
如:10000000.00元,按第一次“全部替换”按钮为:10000,000.00元,按第二次“全部替换”按钮为:10,000,000.00元,按第三次“全部替换”按钮为:“替换0处”完成。
那么,又该如何批量取消千位分隔符呢?CTRL+H调出“查找和替换”对话窗口,勾选“使用通配符”。
在“查找内容”框中填入:([0-9]),([0-9])在“替换为”框中填入:\1\2执行“全部替换”。
如图:后记:由于word的替换功能也不是万能的,由于通配符里只有“非”运算符没有“或”运算,如果数据的小数点后有4位数字,比如1.3527,也会被加上英文逗号,好在word文档中小数点后保留四位的情况并不多前。
如,何在,word,中,设置,数字,的,千位,分隔符,