如何使用另一个文档文本更新文档文本

本文关键字:文档 文本 更新 另一个 何使用 | 更新日期: 2023-09-27 17:56:28

我有一个Windows Form,它有一个WebBrowser控件名称formWebBrowser。我正在使用另一个名为 newThreadBrowser 的 WebBrowser 实例创建一个新的非 UI 线程。在新线程中引用 Web 浏览器控件

当 documentcomplete 事件被触发时,我能够使用 C# - 使用非主线程更新 GUI 中提到的方法将 url 写入文本框

现在,我正在尝试从"newThreadBrowser"的html更新"formWebBrowser"的html。它导致异常指出指定的强制转换无效。

在 WebBrowser 控件中:"指定的强制转换无效",接受的答案说 -

WebBrowser是一个底层的COM组件。一个单元线程,COM 负责以线程安全的方式调用其方法。您的 Navigate() 调用正是出于这个原因,它实际上是在 UI 线程上执行的。不起作用的是 DocumentText 属性,它是在 .NET 包装器中实现的,他们有点摸索代码。当 CLR 中的 COM 互操作支持注意到 MTA 中的线程尝试访问驻留在 STA 上的组件的属性时,它会轰炸。

问题

为了在formWebBrowser中呈现newThreadBrowser的html,我应该怎么做?我不确定Control.Invoke()如何解决这个问题。

注意:此应用程序对性能不重要。因此,即使执行需要一些时间也可以。

参考

  1. 如何更改网络浏览器文档文本?
  2. 如何从网页中提取信息?
  3. http://htmlagilitypack.codeplex.com/

来自 WebBrowser.DocumentText Property

如果要使用字符串处理工具操作 Web 浏览器控件中显示的 HTML 页的内容,请使用此属性。例如,可以使用此属性从数据库加载页面或使用正则表达式分析页面。设置此属性时,Web 浏览器控件在加载指定的文本之前自动导航到 about:blank URL。这意味着当您设置此属性时,将发生"导航"、"已导航"和"文档已完成"事件,并且 Url 属性的值不再有意义。

法典

public partial class Form1 : Form
{
    public void WriteToTextBoxEvent(object sender, WebBrowserDocumentCompletedEventArgs e)
    {
        #region Textbox
        if (this.textBox1.InvokeRequired)
        {
            //BeginInvoke is Asynchronus
            this.textBox1.BeginInvoke(new Action(() => WriteToTextBoxEvent(sender, e)));
        }
        else
        {
            textBox1.Text = e.Url.ToString();
        }
        #endregion
        #region WebBrowser
        if (this.formWebBrowser.InvokeRequired)
        {
            //BeginInvoke is Asynchronus
            this.textBox1.BeginInvoke(new Action(() => WriteToTextBoxEvent(sender, e)));
        }
        else
        {
            var newThreadBrowser = sender as WebBrowser;
            if (sender != null)
            {
                //The function evaluation requires all threads to run
                formWebBrowser.DocumentText = newThreadBrowser.DocumentText;
            }
        }
        #endregion
    }

    System.Windows.Forms.TextBox textBox1 = new TextBox();
    System.Windows.Forms.WebBrowser formWebBrowser = new WebBrowser();
    public Form1()
    {
        WriteLogFunction("App Satrt");
        // Web Browser
        #region Web Browser
        formWebBrowser.Location = new Point(10, 20);
        formWebBrowser.Size = new Size(1200, 900);
        this.Controls.Add(formWebBrowser);
        textBox1.Location = new Point(0, 0);
        textBox1.Size = new Size(800, 10);
        this.Controls.Add(textBox1);
        var th = new Thread(() =>
        {
            var newThreadBrowser = new WebBrowser();
            //To Process the DOM.
            newThreadBrowser.DocumentCompleted += browser_DocumentCompleted;
            //To update URL textbox
            newThreadBrowser.DocumentCompleted += WriteToTextBoxEvent;
            newThreadBrowser.ScriptErrorsSuppressed = true;
            newThreadBrowser.Navigate(GetHomoePageUrl());
            Application.Run();
        });
        th.SetApartmentState(ApartmentState.STA);
        th.Start();
        #endregion
        // Form1
        this.Text = "B2B Crawler";
        this.Size = new Size(950, 950);
    }
    List<string> visitedUrls = new List<string>();
    List<string> visitedProducts = new List<string>();
    private void ExerciseApp(object sender, WebBrowserDocumentCompletedEventArgs e)
    {
        var wbReceived = sender as WebBrowser;
        int catalogElementIterationCounter = 0;
        var elementsToConsider = wbReceived.Document.All;
        string productUrl = String.Empty;
        bool isClicked = false;
        foreach (HtmlElement e1 in elementsToConsider)
        {
            catalogElementIterationCounter++;
            string x = e1.TagName;
            String idStr = e1.GetAttribute("id");
            if (!String.IsNullOrWhiteSpace(idStr))
            {
                //Each Product Navigation
                if (idStr.Contains("catalogEntry_img"))
                {
                    productUrl = e1.GetAttribute("href");
                    if (!visitedProducts.Contains(productUrl))
                    {
                        WriteLogFunction("productUrl -- " + productUrl);
                        visitedProducts.Add(productUrl);
                        isClicked = true;
                        e1.InvokeMember("Click");
                        //nextNavigationUrl = productUrl;
                        break;
                    }
                }
            }
        }

        if (visitedProducts.Count == 4)
        {
            visitedProducts = new List<string>();
            isClicked = true;
            HomoePageNavigate(wbReceived);
        }
        if (!isClicked)
        {
            HomoePageNavigate(wbReceived);
        }
    }
    void browser_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
    {
        ExerciseApp(sender, e);
    }

    private string GetHomoePageUrl()
    {
        return @"C:'Samples_L'MyTableTest.html";
    }
    private void HomoePageNavigate(WebBrowser bw)
    {
        WriteLogFunction("HomoePageNavigate");
        bw.Navigate(GetHomoePageUrl());
    }
    private void WriteLogFunction(string strMessage)
    {
        using (StreamWriter w = File.AppendText("log.txt"))
        {
            w.WriteLine("'r'n{0} ..... {1} ", DateTime.Now.ToLongTimeString(), strMessage);
        }
    }
 }

我的表测试.html

<html>
<head>
    <style type="text/css">
        table {
            border: 2px solid blue;
        }
        td {
            border: 1px solid teal;
        }
    </style>
</head>
<body>
    <table id="four-grid">
         <tr>
            <td>
                <a href="https://www.wikipedia.org/" id="catalogEntry_img63666">
                    <img src="ssss"
                        alt="B" width="70" />
                </a>
            </td>
            <td>
                <a href="http://www.keralatourism.org/" id="catalogEntry_img63667">
                    <img src="ssss"
                        alt="A" width="70" />
                </a>
            </td>
        </tr>
        <tr>
            <td>
                <a href="https://stackoverflow.com/users/696627/lijo" id="catalogEntry_img63664">
                    <img src="ssss"
                        alt="G" width="70" />
                </a>
            </td>
            <td>
                <a href="http://msdn.microsoft.com/en-US/#fbid=zgGLygxrE84" id="catalogEntry_img63665">
                    <img src="ssss"
                        alt="Y" width="70" />
                </a>
            </td>
        </tr>
    </table>
</body>
</html>

如何使用另一个文档文本更新文档文本

首先,请注意,WebBrowser.DocumentText是静态的,它保存原始内容而不进行任何 DOM/AJAX 更改。要获取实际的当前 HTML,请在后台线程上执行此操作:

var html = hiddenWebBrowser.Document.GetElementsByTagName("html")[0].OuterHtml;

然后,可以在 UI 线程上更新另一个WebBrowser实例:

mainForm.BeginInvoke(new Action(() => mainForm.webBrowser.DocumentText = html));

请注意,BeginInvoke是异步的,DocumentText赋值也是异步的。加载 HTML 后,将触发 DocumentCompleted 事件以mainForm.webBrowser