以下WebBrowser
控件正常工作。它浏览“MyTableTest.html”中可用的所有网址。但它基于字符串nextNavigationUrl。下一个导航网址由ExerciseApp函数填充。
if (!visitedProducts.Contains(productUrl))
{
WriteLogFunction("productUrl -- " + productUrl);
visitedProducts.Add(productUrl);
isClicked = true;
//e1.InvokeMember("Click");
nextNavigationUrl = productUrl;
break;
}
实际的webBrowser1.Navigate(url)来自NavigateAsync。
Action startNavigation = () => this.webBrowser1.Navigate(url);
var html = await NavigateAsync(ct, startNavigation);
我不需要将这个url存储在字符串中,而是需要使用InvokeMember
方法。这是必需的,因为在我的真实场景中,我点击了锚标记时执行了javascript函数。
问题
我们如何修改它以使用InvokeMember
?
e1.InvokeMember("Click");
注意:当前代码虽然正常,但仍存在Task is not completing second time [Intermittent Issue] – Async/ Await中提到的一些间歇性问题。但这是一个不同的主题。
CODE
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 2000 sec
var cts = new CancellationTokenSource(2000000);
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)
我演示了here:
await NavigateAsync(ct, () => btn.InvokeMember("click"), 10000); // timeout in 10s