zoukankan      html  css  js  c++  java
  • C#多线程处理webbrowser及InvokeMember("click")无响应的问题

    文章重点:多线程处理webbrowser的相关问题,并解决触发click事件,js无响应问题

    最近刚好碰上一个需求:循环遍历网页元素,找到innerText为指定的内容时,就模拟人工点击

    解决办法:使用WebBrowser将指定位置的文档加载到 WebBrowser 控件中(注:这里的webbrowser是在拉控件的方式,而不是直接在代码中new)

    源码如下:

    private void loadPage(object URL)
            {
                try
                {
                    string url = (string)URL;               
                    browser.Navigate(url);                
                    while (true)
                    {
                       Application.DoEvents();                
                       if(browser.ReadyState != WebBrowserReadyState.Complete) 
                      {
                            break;
                       }
                    }                                
                    HtmlDocument document = browser.Document;
                    HtmlElementCollection elems = browser.Document.GetElementsByTagName("a");
                    foreach (HtmlElement em in elems)
                    {
                        if (em.InnerText == "测试")
                        {          
                            em.InvokeMember("click");//"触发点击事件"
                        }
                    }
                }
                catch (Exception ex)
                {
                    MessageBox.Show(ex.Message);
                }
            }      

    有一点没说到,上面的只适合单线程的,如果执行以上代码的是在新开辟的一个线程中的话,会碰到一系列的问题......(很遗憾,我没有将那些问题记录下来,但相信如果你跟我有着同样的需求的话,即采用多线程的方式处理webbrowser加载的网页内容的话,可以继续看下去,也许对你有所帮助)

    网上一搜,关于webbrowser在多线程中的使用着实会碰到很多问题……后来,经过自己不断的Google(在这过程中你能体会到百度离Google还有多远),有找到了几篇对我有所帮助的文章:

    关于线程的知识:http://www.cnblogs.com/JimmyZheng/archive/2012/06/10/2543143.html

    WebBrowser多线程带来的麻烦http://www.cnblogs.com/xjfhnsd/archive/2010/03/14/1685441.html

    WebBrowser 显示Html内容3点细节技巧: http://www.cnblogs.com/cyq1162/archive/2012/03/27/2419655.html

    接着,我就使用webclient配合webbrowser从而顺利的解决了问题。

    WebClient:下载指定网址的源码

    WebBrowser:navigate一个空白页(具体参考:)

    注:这里的WebBrowser要从代码中new,如果是拉控件的方式创建的,将会报错:"指定的转换无效"

    这里我就写一个以上列出的文章所没有提到的。

    比如,我们要click的网页元素是通过js来触发的,而使用webclient只能下载指定的url的网页源码,无法自动加载相关的js,因此导致在使用invokeMember("click")的时候,没能见到预期效果。

    解决办法:将指定的js文件也下载下来(或者将需要用到的js方法放到本地,使用webclient  载入进来也行)

    我这里说的只是一个大题的思路和解决途径

    最后,贴上一段测试代码:

    C#源码:

    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Data;
    using System.Drawing;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    using System.Windows.Forms;
    using System.Threading;
    using System.Net;
    namespace webbrowser控件
    {
        public partial class Form1 : Form
        {
            public Form1()
            {
                InitializeComponent();
            }
            private void button1_Click(object sender, EventArgs e)
            {
                Control.CheckForIllegalCrossThreadCalls = false;
                ParameterizedThreadStart pt;
                pt = new ParameterizedThreadStart(loadPage);
                Thread td = new Thread(pt);
                td.Name = "主线程";
                td.SetApartmentState(ApartmentState.STA);//在线程启动前设置其单元状态
                td.Start("http://127.0.0.1/test.html");            
            }
            private void loadPage(object URL)
            {
                try
                {
                    string url = (string)URL;
                    WebBrowser browser = new WebBrowser();//当前线程不在单线程单元中,因此无法实例化 ActiveX 控件
                    browser.ScriptErrorsSuppressed = true;
                    //browser.Navigate(url);
                    //browser.DocumentCompleted += browser_DocumentCompleted;
                    browser.Navigate("about:blank");
                    string htmlcode = GetHtmlSource(url);
                    string js = GetHtmlSource("http://127.0.0.1/MY/test/js.html");//载入js
                    browser.Document.Write(js);  
                    textBox1.Text = htmlcode;
                    //while (browser.ReadyState != WebBrowserReadyState.Complete)  //报错“指定的转换无效”
                    //    Application.DoEvents();
                    browser.Document.Write(htmlcode);
                    //MessageBox.Show(browser.DocumentText);
                    HtmlDocument document = browser.Document;
                    HtmlElementCollection elems = browser.Document.GetElementsByTagName("a");
                    foreach (HtmlElement em in elems)
                    {
                        if (em.InnerText == "点击")
                        {          
                            em.InvokeMember("click");//alert("触发点击事件")
                        }
                    }
                }
                catch (Exception ex)
                {
                    MessageBox.Show(ex.Message);
                }
                finally
                {
                    //MessageBox.Show("当前执行线程:"+Thread.CurrentThread.Name);
                }
            }
            //WebClient取网页源码
            private string GetHtmlSource(string Url)
            {
                string text1 = "";
                try
                {
                    WebClient wc = new WebClient();
    
                    text1 = wc.DownloadString(Url);
                }
                catch (Exception ex)
                {
                    MessageBox.Show(ex.Message);
                }
    
                return text1;
            }
    
        }
    }

    test.html:

    <html>
    <head>
    <title></title>
    <script type="text/javascript" src="a.js"></script>
    </head>
    <body>
    <a href="javascript:void();" onclick="t()">点击</a>
    </body>
    </html>

    js:

    <script type="text/javascript">
    function t()
    {
        alert('ddd');
    }
    </script>

    原创文章,转载请注明出处:http://www.cnblogs.com/hongfei/archive/2013/01/05/2846933.html

  • 相关阅读:
    检验Excel中数据是否与数据库中数据重复
    C# 上传文件
    asp.net Excel导入和导出
    完整ASP.Net Excel导入
    C#遍历指定文件夹中的所有文件
    C#获取文件夹下的所有文件的文件名
    UITextField 文本框 只能输入数字 且保留2位小数 实现
    Asp.Net生成无限级菜单
    给Repeater增加button事件,并绑定值
    简洁的Asp.net菜单控件
  • 原文地址:https://www.cnblogs.com/hongfei/p/2846933.html
Copyright © 2011-2022 走看看