C# System.Windows.Forms.WebBrowser等待页面完全加载
我用C# System.Windows.Forms.WebBrowser等待页面完全加载,c#,web-scraping,dynamics-crm,webbrowser-control,C#,Web Scraping,Dynamics Crm,Webbrowser Control,我用等待和异步尝试了很多不同的解决方案。似乎什么都不管用。我无法找到真正完全等待页面完全加载的解决方案。所有的代码都在等待一段时间,但直到页面被加载,并且我在下一个进程中遇到错误 如何将示例代码设置为等待模式,直到在第页上找到Document.GetElementById(“quickFind\u text\u 0”)元素 这是我的密码: private void button7_Click(object sender, EventArgs e) { webBr
等待
和异步
尝试了很多不同的解决方案。似乎什么都不管用。我无法找到真正完全等待页面完全加载的解决方案。所有的代码都在等待一段时间,但直到页面被加载,并且我在下一个进程中遇到错误
如何将示例代码设置为等待模式,直到在第页上找到Document.GetElementById(“quickFind\u text\u 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");
}
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");
}
}
}
请注意,我必须“两次”这样做,否则它将不起作用:
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
While.Busy
多芬特
温德
While.ReadyState 4
多芬特
温德
在C#中也可以这样做吗
编辑: 我的完整代码如下。由于某些原因,async/await不起作用 System.NullReferenceException HResult=0x80004003消息=对象 引用未设置为对象的实例。来源=v.0.0.01
StackTrace:at v._0._0._01.Browser.d_7.MoveNext() 在C:\Users\PC\source\repos\v.0.0.01\v.0.0.01\Browser.cs中:第69行 这是我的密码:
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");
}
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");
}
}
}
使用系统;
使用System.Threading.Tasks;
使用System.Windows.Forms;
名称空间v.0.\u 0.\u 01
{
公共静态类WebBrowserExtensions
{
公共静态任务DocumentCompletedAsync(此WebBrowser wb)
{
var tcs=new TaskCompletionSource();
WebBrowserDocumentCompletedEventHandler=null;
处理程序=(u,e)=>
{
wb.DocumentCompleted-=处理程序;
tcs.TrySetResult(e.Url);
};
wb.DocumentCompleted+=处理程序;
返回tcs.Task;
}
}
公共部分类浏览器:表单
{
公共浏览器()
{
初始化组件();
}
私有异步无效按钮7_单击(对象发送方,事件参数e)
{
webBrowser1.导航(“https://company.crm4.dynamics.com/main.aspx?app=d365default&pagetype=entitylist&etn=opportunity");
等待webBrowser1.DocumentCompletedAsync();//异步魔法
HtmlElement fbLink=webBrowser1.Document.GetElementById(“外壳容器”).Document.GetElementById(“主要内容”).Document.GetElementById(“快速查找按钮0”);
fbLink.InvokeMember(“单击”);
}
}
}
以下是源代码:
现在我还注意到,
quickFind_text_0
和quickFind_按钮_0
总是以相同的单词开头,但是数字在变化,比如quickFind_text_1
和quickFind_按钮_1
或quickFind_text_2
。但是,通过手动单击所有内容,可以使用quickFind\u text\u 0
和quickFind\u按钮\u 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;
}
}
wait
后面的行将在页面完成加载后运行
更新:以下是另一种扩展方法,用于等待特定元素出现在页面中:
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);
}
}
这是一个
System.Windows.Forms.WebBrowser
?加载页面时,它将引发一个事件;把你的刮码放进去。@DourHighArch是的。它是System.Windows.Forms.WebBrowser
。我将尝试这将等待页面加载,我如何才能添加更多的等待?例如,我需要对textbox执行文本输入,然后等待,我有//Thread.Sleep(2000)代码>当前。然后点击按钮。我想我需要等待,直到在页面上找到某个元素,如果30秒未找到,则结束进程。可能是重复链接.Document.GetElementById(…)
时出现问题。不知怎么的,这似乎不对。谢谢你!我不知道问题出在哪里,但我认为这不会等待,因为我在下一个命令中遇到错误。如果我单独运行所有命令,但使用不同的按钮,等待进程自己完成,那么一切正常。页面是否包含frame
s或iframe
s?这可以解释为什么在第一个DocumentCompleted
事件中页面没有完全加载。我在回答中包含了另一个扩展方法,您可能会发现它很有用(WaitForElementAsync
)。