質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

.NET Framework

.NET Framework は、Microsoft Windowsのオペレーティングシステムのために開発されたソフトウェア開発環境/実行環境です。多くのプログラミング言語をサポートしています。

WPF

Windows Presentation Foundation (WPF) は、魅力的な外観のユーザー エクスペリエンスを持つ Windows クライアント アプリケーションを作成するための次世代プレゼンテーション システムです

Q&A

解決済

1回答

2939閲覧

C# WebBrowserを利用してjsが実行された後の通知を受け取る方法

wawawashikawa

総合スコア13

C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

.NET Framework

.NET Framework は、Microsoft Windowsのオペレーティングシステムのために開発されたソフトウェア開発環境/実行環境です。多くのプログラミング言語をサポートしています。

WPF

Windows Presentation Foundation (WPF) は、魅力的な外観のユーザー エクスペリエンスを持つ Windows クライアント アプリケーションを作成するための次世代プレゼンテーション システムです

1グッド

0クリップ

投稿2020/03/13 07:26

現在WebBrowserを用いたツールを作成中の者です。

WebBrowserを用いてWeb画面を読み込んで処理を実施しているのですが、表題の通りwebbrowser1.ReadyStateが完了になったタイミングはサイトのjsの処理が完了しておらず、一部の処理を実行することができません。
(webbrowser1.Document.GetElementById("hoge").All.Countの値が0になったりなど)

たどり着いた先が「非同期処理にてWebBrowserの処理を続行させ、画面の更新があったタイミングで処理を実施する」です。

しかし、非同期処理中にキャストの例外が発生し、実現することができていません。

以下にソースコードを示しますので、どなたかこの問題の解決方法をご教授いただければ幸いです。
※目的はjsとページが全て読み込まれて処理をすることなので、以下のソースコードを改善する他の手段でも構いません。

お手数ですがよろしくお願い致します。

await Task.Run(() => { int iSleepTime = 200; while (webbrowser1.Document.GetElementById("hoge").All.Count==0) { Thread.Sleep(iSleepTime ); System.Windows.Forms.Application.DoEvents(); } });

>while (webbrowser1.Document.GetElementById("hoge").All.Count==0)
でキャストの例外が発生します。
>int iCount= webbrowser1.Document.GetElementById("hoge").All.Count;
として同様に処理を確認しましたがやはり「webbrowser1.Document.GetElementById("hoge").All.Count」この箇所でキャストエラーが発生します。
ちなみに、この例だと場合によっては無限ループする可能性もありますが、できる限り処理を簡潔に書きたかったので諸々の処理は割愛しております。

【やってみたこと】
非同期処理ではなくwebbrowser1.ReadyStateの読み込みが完了した後に、

while (webbrowser1.Document.GetElementById("hoge").All.Count==0) { Thread.Sleep(iSleepTime); System.Windows.Forms.Application.DoEvents(); }

とやってみましたが、画面に表示されているWebBrowserコントロール上、ソース上で該当する箇所は空欄(js読み込みが完了してない)のままでした。

デバッガ上で、returnをかまして一度スレッドを手放すと、すぐに画面上には該当する箇所には値が設定されていました。

補足:
webbrowser1.Document.bodyの変化をキーに非同期で確認するやり方も試しましたが、同じでした、、、
その場合は
>string strBeforeHtml=webbrowser1.Document.Body.OuterHtml;
ここでキャストのエラーが発生しました。

s.k👍を押しています

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2020/03/13 07:46

「キャストの例外」とは何でしょう? NullReferenceException のことですか? WebBrowser.DocumentCompleted イベントのハンドラで処理しても同じ結果ですか?
wawawashikawa

2020/03/14 02:43 編集

早速のご回答ありがとうございます。 SurferOnWww様のおっしゃる通り、イベントハンドラをもう少し深堀りして作成してみました。 自動生成のイベントハンドラではなく、自前で作成したものを追加することにより、求めていた処理が実現できました。 ありがとうございました! 以下に上手く動作したコードを記載します。 /// <summary> /// 画面が読み込まれた際の処理 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void Window_Loaded(object sender, RoutedEventArgs e) { bool complete = false; webbrowser1.DocumentCompleted += delegate { if (complete) return; complete = true; webbrowser1.Document.Window.AttachEventHandler("onload", delegate { // Defer this to make sure all possible onload event handlers got fired System.Threading.SynchronizationContext.Current.Post(delegate { //webbrowser1.Document.GetElementById("hoge").All.Countなど //ここにメイン処理を記載 }, null); }); }; webbrowser1.Navigate("http://exsample.com"); }
退会済みユーザー

退会済みユーザー

2020/03/14 03:53

WebBrowser.DocumentCompleted イベントの発生時点では目的の HtmlElement はまだ存在してないが、DOM の window の load イベント発生時なら存在するので、HtmlWindow の AttachEventHandler メソッドで load イベントにハンドラをアタッチしてそれで処置したということですか?
退会済みユーザー

退会済みユーザー

2020/03/14 04:20

その旨回答欄に書いてこのスレッドはクローズしていただくようお願いします。
wawawashikawa

2020/03/14 04:22

この度は誠にありがとうございました。 大変参考になりました。 こちらの件は仰る通り、クローズしたいと思います。 本当にありがとうございました!!
guest

回答1

0

自己解決

こちらの記事を参考に思っていた処理ができました。

ご回答いただきましたSurferOnWwwさんありがとうございました。
https://stackoverflow.com/questions/18368778/getting-html-body-content-in-winforms-webbrowser-after-body-onload-event-execute

C#

1/// <summary> 2/// 画面が読み込まれた際の処理 3/// </summary> 4/// <param name="sender"></param> 5/// <param name="e"></param> 6private void Window_Loaded(object sender, RoutedEventArgs e) 7{ 8bool complete = false; 9webbrowser1.DocumentCompleted += delegate 10{ 11if (complete) 12return; 13complete = true; 14 15webbrowser1.Document.Window.AttachEventHandler("onload", delegate 16{ 17// Defer this to make sure all possible onload event handlers got fired 18System.Threading.SynchronizationContext.Current.Post(delegate 19{ 20//webbrowser1.Document.GetElementById("hoge").All.Countなど 21//ここにメイン処理を記載 22}, null); 23}); 24}; 25 26webbrowser1.Navigate("http://exsample.com"); 27}

投稿2020/03/14 04:23

wawawashikawa

総合スコア13

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問