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

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

ただいまの
回答率

90.35%

webBrowserコントロールのDocumentCompletedについて

解決済

回答 3

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 845
退会済みユーザー

退会済みユーザー

初心者的質問で申し訳ございませんが、回答していただければ幸いです。
https://teratail.com/questions/160352
上記の質問で無限ループ処理はよくないと回答をいただき、一般的にはDocumentCompletedを利用すればよいことを知りました。
そこで下記のようなDocumentCompletedを利用したものを記述しているのですが、
思った動作をしていません。
理想動作は、
接続先URL1にアクセス→接続先URL1が表示が完了してから
else if (label1.Text == "接続先URL1接続完了")
の部分を実行させたいです。
しかし、完了していない状態のところで動き、
HtmlElement id = elements.GetElementsByName("userName")[0];の部分で下記エラー発生しています。
System.ArgumentOutOfRangeException: ''0' の値は 'index' に対して有効ではありません。'index' は 0 と -1 の間でなければなりません。
パラメーター名:index'
ページによっては複数回DocumentCompletedが発生するものがあると聞きましたが、
その場合の記述例を教えていただけないでしょうか。
また、その他良い記述方法等ございましたらアドバイスお願いいたします。

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Net;
using System.Net.Security;
using System.Runtime.InteropServices;
using System.Security.Cryptography.X509Certificates;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace WindowsFormsApp8
{
   public partial class Form1 : Form
   {
       public Form1()
       {
           InitializeComponent();
       }
       private void button1_Click(object sender, EventArgs e)
       {
           label1.Text = "接続先URL1";
           label1.Refresh();
           string testurl = "接続URL";
           webBrowser1.Navigate(testurl);
       }
       string URL_ST = "検索したいURL1";
       string URL_TH = "検索したいURL2";
       string URL_NE = "検索したいURL3";
       string URL_SE = "検索したいURL4";
       private void webBrowser1_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
       {
           try
           {
               if (e.Url.ToString() == URL_ST)
               {
                   //label1の表示変更
                   label1.Text = "ログイン処理";
                   label1.Refresh();
                   //1番目フレーム内のNameを取得
                   HtmlWindow iframe = webBrowser1.Document.Window.Frames[0];
                   HtmlElementCollection elements = iframe.Document.All;
                   HtmlElement id = elements.GetElementsByName("userName")[0];
                   HtmlElement pw = elements.GetElementsByName("pwd")[0];
                   //ID・passを入力
                   id.InnerText = "admin";
                   pw.InnerText = "password";
                   //Submitボタンをクリック
                   HtmlElement login = elements.GetElementsByName("Submit")[0];
                   login.InvokeMember("click");
               }
               else if (e.Url.ToString() == URL_NE)
               {
                   webBrowser1.Navigate("接続URL2");
               }
               else if (e.Url.ToString() == URL_TH)
               {
                   string filepath = (保存先);
                   // クッキーを取得する。
                   string cookieStr = webBrowser1.Document.Cookie;
                   // WebClientを生成する。
                   WebClient wc = new WebClient();
                   Encoding enc = Encoding.UTF8;
                   // WebClientのヘッダ設定を行う。
                   wc.Headers[HttpRequestHeader.Cookie] = cookieStr;
                   label1.Text = "ダウンロード中";
                   label1.Refresh();
                   wc.DownloadFile("段ロードURL", filepath);
                   wc.Dispose();
          label1.Text = "ダウンロード完了";
                   label1.Refresh();
               }
           }
           catch (Exception)
           {
               label1.Text = "例外の発生";
               label1.Refresh();
           }
       }
   }
}


追記

 追記

上記に変更したところ、ダウンロードは出来るようになりました。
このソースで記述的におかしい・こうしたほうが良いなどありましたらアドバイスお願いします。

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

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

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

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

質問への追記・修正、ベストアンサー選択の依頼

  • Zuishin

    2018/11/28 15:48

    できるようになったなら解決済みにしてください。リファクタリング作業を依頼するところではありません。親切でサービスすることはあっても基本的に自分でしてください。

    キャンセル

  • Zuishin

    2018/11/28 15:54

    何の事情か知りませんが、削除しないでください。自分だけの質問ではありません。同じような問題を抱える他の人のための質問と回答でもあります。

    キャンセル

  • 退会済みユーザー

    2018/11/29 01:08

    複数のユーザーから「意図的に内容が抹消された質問」という意見がありました
    解決後に編集機能を用いて質問内容を改変し関係のない内容にしたり、内容を削除する行為は禁止しています。
    投稿していただいた質問は、後に他の誰かが困ったときに助けになる情報資産になると考えるからです。
    「質問を編集する」ボタンから編集を行い、他のユーザにも質問内容が見えるように修正してください。

回答 3

checkベストアンサー

0

DocumentCompleted はページだけでなく画像やスクリプトのダウンロードでも発生します。ラベルテキストで分岐すると、画像のダウンロードで name が userName となるタグが無い(html ではないので無くて当然です)ことになり、例外が発生します。

e.Url を見て何がダウンロードされたのか識別してください。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/11/28 14:57

    あと、webBrowser1.Navigate が終わってもページの読み込みは終わっていないので接続完了と思ってはダメです。

    キャンセル

  • 2018/11/28 15:47 編集

    諸事情により削除させていただきます。

    キャンセル

0

DocumentCompletedイベント内でURL2、URL3へNavigateすればいいのではないでしょうか?
どのURLへNabigateした時なのかはフラグでも設ければいいのではないかと

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

0

前回の質問の回答で、以下のことを書きましたが、これはフレーム構成でなくとも、外部ファイルの読込等で発生します。
(説明不足でしたね。ゴメンナサイ。)

ただし、そのページがフレーム構成(インラインフレームを含む)の場合、DocumentCompletedイベントが何度も発生する場合があります。
その場合、私はイベントハンドラの第2引数(WebBrowserDocumentCompletedEventArgs e)のUrlプロパティのUrl情報がナビゲートしたUrl(提示例ではWebBrowser1.Url)のそれと同じ場合、読込完了と判断しています。

恐らく、Webページ本体の読み込みが完了していないため、まだ読み込まれていない要素を参照しようとして今回のエラーになっている可能性があります。

試しに、DocumentCompletedイベントハンドラの第2引数(e)のe.Urlにどのような値がセットされているかウォッチしてみるといいかも知れません。

今回の回避策として試してほしいのは、DocumentCompletedイベントハンドラ内で、例えばif(e.Url.Tostring == WebBrowser1.Url.ToString)のような条件を付けることです。
(専門がVBのため、おかしなところがあるかも知れません。)
※関係演算子の誤りを修正しました。

        private void webBrowser1_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
        {
            if(e.Url.Tostring != WebBrowser1.Url.ToString) return;

            // 後はやりたい処理を以下に書く



            label1.Text = "接続先URL1接続完了";  //追記:ここでようやくラベル変更可能
        }

 追記

button1_Clickで、webBrowser1.Navigateの後にlabel1.Textを"接続先URL1接続完了"に書き換えていますが、これでは読込完了前にlabel1.Textが"接続先URL1接続完了"になってしまいます。
正しくは、DocumentCompletedイベントで対象のURLの読み込みが確認できてから、label1.Textを"接続先URL1接続完了"にすればよいです(上記コードの追記コメント参照)。

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/11/28 14:58 編集

    `==` ですか? `!=` ではなく?

    キャンセル

  • 2018/11/28 15:04

    ご指摘の通りです。何ともお恥ずかしい...(*μ_μ)

    キャンセル

  • 2018/11/28 15:48 編集

    諸事情により削除させていただきます。

    キャンセル

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

  • ただいまの回答率 90.35%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

同じタグがついた質問を見る