c# - System.Windows.Forms.WebBrowser 等到页面完全加载
问题描述
我一直在尝试使用wait
和的许多不同解决方案async
。似乎没有任何效果。我无法找到实际上完全等待页面完全加载的解决方案。所有代码都在等待一段时间,但直到页面加载完毕并且我在下一个过程中遇到错误。
如何将示例代码设置为等待模式,直到Document.GetElementById("quickFind_text_0")
在页面上找到元素?
这是我的代码:
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");
}
PS我必须这样做“两次”否则它不起作用:
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# 中做同样的事情?
编辑:
我的完整代码如下。由于某种原因异步/等待不起作用。
System.NullReferenceException HResult=0x80004003 Message=对象引用未设置为对象的实例。Source=v.0.0.01
StackTrace:位于 C:\Users\PC\source\repos\v.0.0.01\v.0.0 中的 v._0._0._01.Browser.<button7_Click>d__7.MoveNext()。 01\Browser.cs:第 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
andquickFind_button_1
或quickFind_text_2
and quickFind_button_2
。但是,通过手动单击,一切都适用于quickFind_text_0
和quickFind_button_0
。
解决方案
这是一个易于等待DocumentCompleted
事件的扩展方法:
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
行将在页面完成加载后运行。
更新:这是等待特定元素出现在页面中的另一种扩展方法:
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 修改页面的单击事件后使用它:
someButton.InvokeMember("click");
var mainContentElement = await webBrowser1.WaitForElementAsync("mainContent", 5000);
推荐阅读
- python - Argparse 不会解析我在命令行中传递的任何参数
- ios - 使用 ImagePickerViewController 从图库中选择圆形裁剪图像
- c# - 基于请求的 Asp Net Core 2.0 身份验证
- symfony - Symfony 3 - 渲染视图后替换字符串(注释)
- amazon-web-services - 如何知道 EC2 是否已注册到某个负载均衡器?
- laravel - 文件存储不工作。拉拉维尔 5
- c# - C# 询问用户需要合并的 PDF 位于哪个目录中。然后问用户什么新的子文件夹将被称为合并的 PDF 将去哪里?
- python - 如何在更新触发器之前使用 postgresql?这不执行只正确编译
- sql - 将列转换为单行并选择唯一条目
- python - list_directories_and_files 上缺少 Azure FileProperties 内容