The project has a need to get some data from the site. The problem is that I cannot work with api for certain reasons, and the content of the site itself is generated by the script. I collected the answers from WebBrowser (which is exactly from Vinform, there are more possibilities in it), it works in principle, but only if I have a winform project and the form has this same browser. If I initialize the WebBrowser instance and do not have it on the form, the body property is always = null. It is necessary either to make WebBrowser produce the necessary content (hide it somehow), or in any other way to get this html.

In the wpf project itself there is a form with a button; this button hangs on the button:

System.Windows.Forms.WebBrowser browser = new System.Windows.Forms.WebBrowser(); browser.ScriptErrorsSuppressed = true; browser.Navigate("https://temp-mail.org/ru"); Thread.Sleep(10000); //думал мб не хватает времени прогрузить MessageBox.Show(browser?.Document?.Body?.InnerHtml); 

Already decided in another way (from kommnets). Still, explain if anyone knows why body = null.

1 answer 1

Still, explain if anyone knows why body = null.

That is why:

Thread.Sleep(10000); //думал мб не хватает времени прогрузить

Use Thread.Sleep to wait for the document to load. WebBrowser - a wrapper over an Internet Explorer ActiveX element that needs to process messages in a GUI stream in order to work correctly. Calling Thread.Sleep blocks it, so that although the document has time to load the "transport layer" in 10 seconds, WebBrowser cannot react to this and set the value of the Document property. For everything to work, you need to wait without interrupting message processing.

Unfortunately, WinForms is a very old library and in WebBrowser I could not find an asynchronous loading method that would allow using await . So the only (standard) way is to subscribe to an event:

 private void button1_Click(object sender, EventArgs e) { System.Windows.Forms.WebBrowser browser = new System.Windows.Forms.WebBrowser(); browser.ScriptErrorsSuppressed = true; browser.DocumentCompleted += browser_DocumentCompleted; browser.Navigate("https://temp-mail.org/ru"); } void browser_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e) { MessageBox.Show((sender as WebBrowser).Document.Body.InnerHtml); } 

To implement wait more conveniently, create a helper method to wait for an event using a TaskCompletionSource :

 using System; using System.Reflection; using System.Threading.Tasks; namespace WinformsTest { public class AsyncTools { /// <summary> /// Получает объект Task, который может использоваться для ожидания срабатывания указанного события /// </summary> /// <param name="o">Объект-источник события</param> /// <param name="evt">Имя события</param> public static Task<object> GetTaskFromEvent(object o, string evt) { if (o == null || evt == null) throw new ArgumentNullException("Please pass non-null arguments"); EventInfo einfo = o.GetType().GetEvent(evt); if (einfo == null) { throw new ArgumentException(String.Format("*{0}* has no *{1}* event", o, evt)); } TaskCompletionSource<object> tcs = new TaskCompletionSource<object>(); MethodInfo mi = null; Delegate deleg = null; EventHandler handler = null; //код обработчика события handler = (s, e) => { mi = handler.Method; deleg = Delegate.CreateDelegate(einfo.EventHandlerType, handler.Target, mi); einfo.RemoveEventHandler(s, deleg); //отцепляем обработчик события tcs.TrySetResult(null); //сигнализируем о наступлении события }; mi = handler.Method; deleg = Delegate.CreateDelegate(einfo.EventHandlerType, handler.Target, mi); //получаем делегат нужного типа einfo.AddEventHandler(o, deleg); //присоединяем обработчик события return tcs.Task; } } } 

Then waiting for the download of the document can be done using await (.NET 4.5+):

 var task = AsyncTools.GetTaskFromEvent(webBrowser1,"DocumentCompleted"); webBrowser1.Navigate("http://example.com/"); await task;