System.Windows.Forms.WebBrowser等待页面完全加载完毕 [英] System.Windows.Forms.WebBrowser wait until page has been fully loaded

查看:116
本文介绍了System.Windows.Forms.WebBrowser等待页面完全加载完毕的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我一直在尝试通过 wait async 使用许多不同的解决方案.似乎没有任何作用.我无法找到实际上完全等到页面已完全加载的解决方案.所有代码都在等待一段时间,但要等到页面加载完毕后才能进行下一个处理.

I have been trying a lot of different solutions with wait and async. Nothing seems to work. I was not able to find solution that actually fully waits until page has been fully loaded. All codes are waiting some time but not until page has been loaded and I am getting an error on next process.

如何在页面上找到 Document.GetElementById("quickFind_text_0")元素之前将示例代码设置为等待模式?

How I can set for example code into wait mode until Document.GetElementById("quickFind_text_0") element has been found on page?

这是我的代码:

    private void button7_Click(object sender, EventArgs e)
    {

        webBrowser1.Navigate("https://company.crm4.dynamics.com/main.aspx?app=d365default&pagetype=entitylist&etn=opportunity");

        webBrowser1.Document.GetElementById("shell-container").Document.GetElementById("quickFind_text_0").SetAttribute("value", "Airbus");

        webBrowser1.Document.GetElementById("shell-container").Document.GetElementById("quickFind_text_0").InnerText = "Airbus";

        //Thread.Sleep(2000);

        HtmlElement fbLink = webBrowser1.Document.GetElementById("shell-container").Document.GetElementById("mainContent").Document.GetElementById("quickFind_button_0"); ;
        fbLink.InvokeMember("click");
    }

P.S.我必须两次"执行此操作,否则无法正常工作:

P.S. I have to do this "twice" otherwise it is not working:

    webBrowser1.Document.GetElementById("shell-container").Document.GetElementById("quickFind_text_0").SetAttribute("value", "Airbus");

    webBrowser1.Document.GetElementById("shell-container").Document.GetElementById("quickFind_text_0").InnerText = "Airbus";

在VBA中,这有效:

    While .Busy
        DoEvents

    Wend
    While .ReadyState <> 4
        DoEvents
    Wend

是否可以在C#中执行相同的操作?

Is it possible to do the same in C#?

我的完整代码如下.由于某种原因,异步/等待无法正常工作.

My full code below. For some reason async/await does not work.

System.NullReferenceException HResult = 0x80004003消息=对象引用未设置为对象的实例.来源= v.0.0.01
StackTrace:位于v._0._0._01.Browser.d__7.MoveNext()在C:\ Users \ PC \ source \ repos \ v.0.0.01 \ v.0.0.01 \ Browser.cs:第69行

System.NullReferenceException HResult=0x80004003 Message=Object reference not set to an instance of an object. Source=v.0.0.01
StackTrace: at v._0._0._01.Browser.d__7.MoveNext() in C:\Users\PC\source\repos\v.0.0.01\v.0.0.01\Browser.cs:line 69

这是我的代码:

using System;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace v.0._0._01
{

    public static class WebBrowserExtensions
    {
        public static Task<Uri> DocumentCompletedAsync(this WebBrowser wb)
        {
            var tcs = new TaskCompletionSource<Uri>();
            WebBrowserDocumentCompletedEventHandler handler = null;
            handler = (_, e) =>
            {
                wb.DocumentCompleted -= handler;
                tcs.TrySetResult(e.Url);
            };
            wb.DocumentCompleted += handler;
            return tcs.Task;
        }
    }

    public partial class Browser : Form
    {

        public Browser()
        {
            InitializeComponent();
        }

        private async void button7_Click(object sender, EventArgs e)
        {

            webBrowser1.Navigate("https://company.crm4.dynamics.com/main.aspx?app=d365default&pagetype=entitylist&etn=opportunity");
            await webBrowser1.DocumentCompletedAsync(); // async magic
            HtmlElement fbLink = webBrowser1.Document.GetElementById("shell-container").Document.GetElementById("mainContent").Document.GetElementById("quickFind_button_0"); ;
            fbLink.InvokeMember("click");

        }

    }

}

这是源代码:

现在我也注意到 quickFind_text_0 quickFind_button_0 总是以相同的词开头,但数字却像 quickFind_text_1 quickFind_button_1 quickFind_text_2 quickFind_button_2 .但是,通过手动单击,所有内容都可以使用 quickFind_text_0 quickFind_button_0 .

Also now I have noticed that quickFind_text_0 and quickFind_button_0 always starts with same words but numbers are changing like quickFind_text_1 and quickFind_button_1 or quickFind_text_2 and quickFind_button_2. However by manual clicking everything works with quickFind_text_0 and quickFind_button_0.

推荐答案

以下是扩展方法,可轻松等待 DocumentCompleted 事件:

Here is an extension method for easy awaiting of the DocumentCompleted event:

public static class WebBrowserExtensions
{
    public static Task<Uri> DocumentCompletedAsync(this WebBrowser wb)
    {
        var tcs = new TaskCompletionSource<Uri>();
        WebBrowserDocumentCompletedEventHandler handler = null;
        handler = (_, e) =>
        {
            wb.DocumentCompleted -= handler;
            tcs.TrySetResult(e.Url);
        };
        wb.DocumentCompleted += handler;
        return tcs.Task;
    }
}

它可以这样使用:

private async void button1_Click(object sender, EventArgs e)
{

    webBrowser1.Navigate("https://company.crm4.dynamics.com/main.aspx");
    await webBrowser1.DocumentCompletedAsync(); // async magic
    HtmlElement fbLink = webBrowser1.Document.GetElementById("quickFind_button_0");
    fbLink.InvokeMember("click");
}

await 之后的行将在页面加载完成后运行.

The lines after the await will run after the page has completed loading.

更新:这是等待特定元素显示在页面中的另一种扩展方法:

Update: Here is another extension method for awaiting a specific element to appear in the page:

public static async Task<HtmlElement> WaitForElementAsync(this WebBrowser wb,
    string elementId, int timeout = 30000, int interval = 500)
{
    var stopwatch = Stopwatch.StartNew();
    while (true)
    {
        try
        {
            var element = wb.Document.GetElementById(elementId);
            if (element != null) return element;
        }
        catch { }
        if (stopwatch.ElapsedMilliseconds > timeout) throw new TimeoutException();
        await Task.Delay(interval);
    }
}

例如,在调用使用XMLHttpRequest修改页面的click事件后,可以使用它:

It can be used for example after invoking a click event that modifies the page using XMLHttpRequest:

someButton.InvokeMember("click");
var mainContentElement = await webBrowser1.WaitForElementAsync("mainContent", 5000);

这篇关于System.Windows.Forms.WebBrowser等待页面完全加载完毕的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆