我有一个WebBrowser
控件是Windows Forms项目。它浏览“MyTableTest.html”中可用的所有网址。此页面中有四个网址,网络浏览器会逐个浏览每个网址。一旦到达最后一个,它应该再次到达第一个。它在第一次迭代中工作正常 - 但不会在第二次迭代中转到url。这是一个间歇性问题 - 某些时候它起作用。
似乎(从日志中)他等待的任务没有完成。如何使它在第二次迭代中工作呢?
注意:MyTableTest.html在下面给出
注意:这取决于帖子Get ReadyState from WebBrowser control without DoEvents
问题
startNavigation();
WriteLogFunction("Location 1");
// wait for DOM onload event, throw if cancelled
await onloadTcs.Task;
//ISSUE: Not reaching this location at second time navigation
WriteLogFunction("Location 2");
代码
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
this.Load += MainForm_Load;
}
List<string> visitedProducts = new List<string>();
string nextNavigationUrl = String.Empty;
// Form Load event handler
async void MainForm_Load(object sender, EventArgs e)
{
// cancel the whole operation in 20 sec
var cts = new CancellationTokenSource(20000);
//urlStore.Add(@"C:\Samples_L\MyTableTest.html");
nextNavigationUrl = GetHomoePageUrl();
await NavigateInLoopAsync(cts.Token);
}
// navigate to each URL in a loop
async Task NavigateInLoopAsync(CancellationToken ct)
{
bool isIterationComplete = false;
while (!isIterationComplete)
{
string url = String.Empty;
if (String.IsNullOrEmpty(nextNavigationUrl))
{
WriteLogFunction("Close");
isIterationComplete = true;
}
else
{
url = nextNavigationUrl;
ct.ThrowIfCancellationRequested();
WriteLogFunction("Calling NavigateAsync");
Action startNavigation = () => this.webBrowser1.Navigate(url);
var html = await NavigateAsync(ct, startNavigation);
}
}
}
// asynchronous navigation
async Task<string> NavigateAsync(CancellationToken ct, Action startNavigation)
{
var onloadTcs = new TaskCompletionSource<bool>();
EventHandler onloadEventHandler = null;
WriteLogFunction("Inside Function NavigateAsync");
WebBrowserDocumentCompletedEventHandler documentCompletedHandler = delegate
{
// DocumentCompleted may be called several time for the same page,
// if the page has frames
if (onloadEventHandler != null)
return;
// so, observe DOM onload event to make sure the document is fully loaded
onloadEventHandler = (s, e) =>
onloadTcs.TrySetResult(true);
this.webBrowser1.Document.Window.AttachEventHandler("onload", onloadEventHandler);
};
this.webBrowser1.DocumentCompleted += documentCompletedHandler;
try
{
using (ct.Register(() => onloadTcs.TrySetCanceled(), useSynchronizationContext: true))
{
startNavigation();
WriteLogFunction("Location 1");
// wait for DOM onload event, throw if cancelled
await onloadTcs.Task;
//ISSUE: Not reaching this location at second time navigation
WriteLogFunction("Location 2");
}
}
finally
{
this.webBrowser1.DocumentCompleted -= documentCompletedHandler;
if (onloadEventHandler != null)
this.webBrowser1.Document.Window.DetachEventHandler("onload", onloadEventHandler);
}
WriteLogFunction("Place 3");
// the page has fully loaded by now
// optional: let the page run its dynamic AJAX code,
// we might add another timeout for this loop
do { await Task.Delay(500, ct); }
while (this.webBrowser1.IsBusy);
//Call Processing -- Added By Lijo
ExerciseApp(this.webBrowser1, null);
// return the page's HTML content
return this.webBrowser1.Document.GetElementsByTagName("html")[0].OuterHtml;
}
private void ExerciseApp(object sender, WebBrowserDocumentCompletedEventArgs e)
{
WriteLogFunction("ExerciseApp");
var wb = sender as WebBrowser;
int catalogElementIterationCounter = 0;
var elementsToConsider = wb.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;
}
}
}
}
WriteLogFunction(visitedProducts.Count.ToString());
WriteLogFunction(nextNavigationUrl);
if (visitedProducts.Count == 4)
{
WriteLogFunction("Condition B");
visitedProducts = new List<string>();
}
if (!isClicked)
{
WriteLogFunction("Condition C");
nextNavigationUrl = GetHomoePageUrl();
}
}
private void HomoePageNavigate()
{
webBrowser1.Navigate(GetHomoePageUrl());
}
private string GetHomoePageUrl()
{
return @"C:\Samples_L\MyTableTest.html";
}
private void WriteLogFunction(string strMessage)
{
using (StreamWriter w = File.AppendText("log.txt"))
{
w.WriteLine("\r\n{0} ..... {1} ", DateTime.Now.ToLongTimeString(), strMessage);
}
}
}
MyTableTest.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>
答案 0 :(得分:1)
&#34;位置1&#34;是打印但不是&#34;位置2&#34;。你的建议是什么? 克服这个?你能重现这个问题吗?
我还没有尝试过复制,但就像我在评论中所说的那样,显而易见的是,DocumentCompleted
或window.onload
并未因特定网址被解雇。如果页面无法完全加载,或者例如如果URL无效或服务器无法访问。这就是超时逻辑的用途。
在documentCompletedHandler
的开头添加一个跟踪,在onloadEventHandler
内添加一个跟踪:
onloadEventHandler = (s, e) => { Log("inside onloadEventHandler");
onloadTcs.TrySetResult(true); }
了解被解雇的内容以及未解决的问题。
此外,您还应该实现WebBrowser
Feature Control以启用现代IE功能。这通常也会影响网页的加载方式。从here复制SetFeatureBrowserEmulation
。