碰到一个无比坑爹,外加蛋疼乳酸的问题。从昨天晚上发现bug,到今天下午解决问题,搞了大半天的时间。光是找问题就花了半天,解决问题的方法简单,但是方案的形成也是无比纠结的过程。
背景:webbrowser获取页面上的验证码,然后解析验证码回写到页面。解析和回写没什么问题,问题主要在获取页面验证码上。
在网上搜索得到这么一段代码:
IHTMLControlElement img = (IHTMLControlElement)webBrowser1.Document.Images["vcode_img"].DomElement; IHTMLControlRange range = (IHTMLControlRange)((HTMLBody)html.body).createControlRange(); range.add(img); range.execCommand("Copy", false, null); img = null; range = null; html = null; if (Clipboard.ContainsImage()) this.pictureBox1.Image = Clipboard.GetImage(); else MessageBox.Show("执行不成功"); Clipboard.Clear();
获取验证码图片的核心也在这里。复制图片数据到内存,然后从剪贴板读取到pictureBox控件。
图片很顺利的取出来了。
但是实际调用的时候,发现“时灵时不灵”,不时的会冒出“执行不成功”的弹框。
刚开始以为是线程运行顺序导致的,加了一堆Thread.Sleep,发现毫无改善。
各种测试,毫无头绪......
无意中发现某一次报错时,页面上选中了部分文字。难道是这里的问题?于是重点测试,每次选中文字之后,解析验证码,报错。而没有选中文字时,运行这部分代码,安然通过。我X,这是什么狗血情况,问题居然出在页面当前有选中文字上??郁闷呐》。。。。。
找到问题后,解决问题的方向就很明确了。在执行这段代码之前,取消页面选择。
问题又来了,对于我这么一个没搞过js、html的c#初级猿,怎么取消webbrowser页面选择文字还真是难到我了,试过很多方法,focus,select,moveStart,move...通通滴死啦死啦滴...
过程很坎坷,结果很简洁。一句txtRange.execCommand("Unselect");搞定。
完整代码:
var code = ""; var body = (mshtml.HTMLBodyClass)((mshtml.HTMLDocumentClass)wbsContent.Document.Window.Frames[0].Document.DomDocument).body; IHTMLControlElement img = (IHTMLControlElement)((mshtml.HTMLDocumentClass)wbsContent.Document.Window.Frames[0].Document.DomDocument).images.item("imgCode"); IHTMLControlRange range = (IHTMLControlRange)body.createControlRange(); IHTMLTxtRange txtRange = body.createTextRange(); txtRange.execCommand("Unselect"); range.add(img); range.execCommand("Copy"); img = null; range = null; if (Clipboard.ContainsImage()) { code = UnCodeBase.GetVarifyCodeFromWinWinTask((Bitmap)Clipboard.GetImage()); var txtVrf = (mshtml.HTMLInputElementClass)((mshtml.HTMLDocumentClass)wbsContent.Document.Window.Frames[0].Document.DomDocument).all.item("code"); txtVrf.setAttribute("value", code); return true; }
这是Frame的情况,相信没有Frame的情况应该可以照着这个思路处理。
问题解决了的时候,还是很开心的,虽然还是觉得这个问题很让人郁闷.