问题
Code below.
I am trying to navigate to a website and read information, the problem is that Navigate doesn't work, the only event that is called is Navigating and the printed Url is empty, the other events are never called. what am I missing? do I have to use Form class in order to navigate? can't I use it programatically from a Console application?
Please help.
class WebNavigator
{
private readonly WebBrowser webBrowser;
public WebNavigator()
{
webBrowser = new WebBrowser
{
AllowNavigation = true
};
webBrowser.Navigated += webBrowser_Navigated;
webBrowser.Navigating += webBrowser_Navigating;
webBrowser.DocumentCompleted += webBrowser_DocumentCompleted;
}
// Navigates to the given URL if it is valid.
public void Navigate(string address)
{
if (String.IsNullOrEmpty(address)) return;
if (address.Equals("about:blank")) return;
if (!address.StartsWith("http://") &&
!address.StartsWith("https://"))
{
address = "http://" + address;
}
try
{
Trace.TraceInformation("Navigate to {0}", address);
webBrowser.Navigate(new Uri(address));
}
catch (System.UriFormatException)
{
Trace.TraceError("Error");
return;
}
}
// Occurs when the WebBrowser control has navigated to a new document and has begun loading it.
private void webBrowser_Navigated(object sender, WebBrowserNavigatedEventArgs e)
{
Trace.TraceInformation("Navigated to {0}", webBrowser.Url);
}
// Occurs before the WebBrowser control navigates to a new document.
private void webBrowser_Navigating(object sender, WebBrowserNavigatingEventArgs e)
{
Trace.TraceInformation("Navigating to {0}", webBrowser.Url);
}
private void webBrowser_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
{
var wb = sender as WebBrowser;
Trace.TraceInformation("DocumentCompleted {0}", wb.Url);
}
}
回答1:
I would make use of await/async.
Usage:
static async void DoWork()
{
var html = await GetHtmlAsync("http://www.google.com/");
}
The utility method
static Task<string> GetHtmlAsync(string url)
{
var tcs = new TaskCompletionSource<string>();
var thread = new Thread(() =>
{
WebBrowser wb = new WebBrowser();
WebBrowserDocumentCompletedEventHandler documentCompleted = null;
documentCompleted = async (o, s) =>
{
wb.DocumentCompleted -= documentCompleted;
await Task.Delay(2000); //Run JS a few seconds more
tcs.TrySetResult(wb.DocumentText);
wb.Dispose();
Application.ExitThread();
};
wb.ScriptErrorsSuppressed = true;
wb.DocumentCompleted += documentCompleted;
wb.Navigate(url);
Application.Run();
});
thread.SetApartmentState(ApartmentState.STA);
thread.Start();
return tcs.Task;
}
回答2:
You mentioned this is a console app. For WebBrowser to work in a console app, you need to make sure the browser's thread is an STA thread (thread.SetApartmentState(ApartmentState.STA). Also, to be able to handle events, the thread must pump messages (Application.Run). Considering this, you may want to create a separate thread (from your main console thread) to run WebBrowser.
回答3:
Thanks for the answers. The problem was solved by adding this while clause including Application.DoEvents();
webBrowser.Navigate(new Uri(address));
while (!navigationCompleted)
{
Application.DoEvents();
Thread.Sleep(navigationPollInterval);
}
I am not sure if this is the best solution, I would be grateful to hear better solutions.
来源:https://stackoverflow.com/questions/18428616/webbrowser-navigating-function-doesnt-work-and-handlers-are-not-called