DOBON.NET DOBON.NETプログラミング掲示板過去ログ

Navigateでエラーがでてしまう

環境/言語:[XP VB.Net]
分類:[.NET]

お世話になります。

以下コードにてエラーになり,解決方法が分かりません。
Navigateできる箇所とできない箇所があり,できない箇所については,
以下の通りとなっています。
ActiveXが無効になっているらしいのですが,どのように有効にするのかも分かりません。
ご教授のほど,よろしくお願い致します。

環境
VB.net
OS XP

エラー内容:
'InvalidActiveXStateException'のハンドルされていない例外がaxinterop.shdocvw.dllで発生しました。

ソース:
Dim ie As New AxSHDocVw.AxWebBrowser

ie.Navigate("http://www.google.co.jp/")

自分なりに調べた結果:
無効な状態にある ActiveX コントロールを参照したときにスローされる例外。
ActiveX コントロールのパブリック プロパティおよびパブリック メソッドは、
ActiveX コントロールが完全にインスタンス化および初期化された後でなければ参照できません。
ためしていないのですが,
Form.ControlsなどにAddしないといけないのかも。
もしくは,VisibleをFalseにしてみたらどうでしょう?
ご返答ありがとうございます。

Form.Control.add(ie)
をieオブジェクトの設定後に行っているのですが,
できませんでした。

また,visibleをfalseにしてみましたが,これも,同じ結果でした。

ご報告まで
Load イベントあたりよりも前の時点では無理です。
Navigate は Load イベントで行うといいでしょう。
もちろん、そのロードされているフォーム上に WebBrowser が含まれていなければなりません(フォームあるいはその子コントロールのControls に Add されてないと駄目)。
Loadイベントとインスタンス時にNavigateしましたが,無理でした。
 また,Loadイベント内にて,Form.Controls.add(IE)を行なった後,
Navigateしたのですが,無理でした。

 Formが表示された後,何かのイベントにて,Navigateすることは出来たのですが,
表示と共に,Navigateしたいと考えています。この方法は,出来ないのでしょうか?

■No17640に返信(Hongliangさんの記事)
> Load イベントあたりよりも前の時点では無理です。
> Navigate は Load イベントで行うといいでしょう。
> もちろん、そのロードされているフォーム上に WebBrowser が含まれていなければなりません(フォームあるいはその子コントロールのControls に Add されてないと駄目)。
> Loadイベントとインスタンス時にNavigateしましたが,無理でした。
>  また,Loadイベント内にて,Form.Controls.add(IE)を行なった後,
> Navigateしたのですが,無理でした。

そりゃおかしいですね。
少なくとも Load のハンドラの中でなら成功するはずです。

念のため、ブラウザコントロールを Show() してから Navigate() してみるとか。
フォームのActivatedイベントハンドラ内で次のようにしてみると表示できました。

Static firstCall As Boolean = True
If firstCall Then
    ie.Navigate("http://www.google.co.jp/")
    firstCall = False
End If

.NET 2.0では、Activatedイベントに替えてShownイベントを使うといいようです。
こちらに参考情報があります。

http://www.atmarkit.co.jp/fdotnet/dotnettips/470formshown/formshown.html
■No17667に返信(tororoさんの記事)
> Loadイベントとインスタンス時にNavigateしましたが,無理でした。
>  また,Loadイベント内にて,Form.Controls.add(IE)を行なった後,
> Navigateしたのですが,無理でした。

んん? おかしいな。

Public Class Form1
    Inherits System.Windows.Forms.Form

    <STAThread> Public Shared Sub Main()
        System.Windows.Forms.Application.Run(New Form1())
    End Sub

    Private browser As New AxSHDocVw.AxWebBrowser()

    Public Sub New()
        browser.Dock = System.Windows.Forms.DockStyle.Fill
        Me.Controls.Add(browser)
    End Sub

    Private Sub Form1_Load(ByVal sender As System.Object, _
                           ByVal e As System.EventArgs) _
                       Handles Me.Load
        browser.Navigate("http://www.yahoo.co.jp/")
    End Sub
End Class

事前に Form の Controls に Add しておき
/*
 ここではコンストラクタに直接記述しています。
 VS を使って WebBrowser コントロールを D&D 場合は、
 InitializeComponent メソッド内にこのコードが追加されるはずです。
 InitializeComponent 自体はコンストラクタが呼び出しています。
*/
その後の Load イベントで Navigate します。
最初、Loadイベントハンドラ内でControls.Addの後Navigateしたときは表示できなかったので、ActivatedイベントハンドラでNavigateするように変更して表示できたのですが、その後再度LoadイベントハンドラでNavigateするように戻してみたところ、不思議なことに表示できました。

3台のPCで試してみたのですが、最初の現象は再現せず、いずれも、LoadイベントハンドラからNavigateできました。

表示できなかったときのコードは保存していないので、もうチェックできないのですが、もしかしたら何か間違えていたのかもしれません。
Webbrowserコントロールの本体の
shdocvw.dllですが
結構良く参照できなかったり、エラーがでるので
regsvrなどでIE系のDLLを再登録したり、
レジストリ周りやMSDNなどで同様のエラーがないか
チェックしたほうがいいと思います。

Navigateや、IE系のコンポーネントを使うとすさまじくCPU消費率
があがって失敗することがあるので、Load時に負荷がかかりすぎて
いなかったか、チェックしてみたらよいと思います。
みなさん,回答ありがとうございます。
Showを行なった後,Navigateしましたが,無理でした。
Shownイベントがないんですが,何か宣言しなければならないのでしょうか?
特にCPUの消費率が上がっているという現象はおきていませんでした。
急ぎ連絡まで。

■No17683に返信(ヤマ@文系さんの記事)
> Webbrowserコントロールの本体の
> shdocvw.dllですが
> 結構良く参照できなかったり、エラーがでるので
> regsvrなどでIE系のDLLを再登録したり、
> レジストリ周りやMSDNなどで同様のエラーがないか
> チェックしたほうがいいと思います。
>
> Navigateや、IE系のコンポーネントを使うとすさまじくCPU消費率
> があがって失敗することがあるので、Load時に負荷がかかりすぎて
> いなかったか、チェックしてみたらよいと思います。
>
2006/09/28(Thu) 09:04:06 編集(投稿者)
2006/09/28(Thu) 09:01:45 編集(投稿者)

> Showを行なった後,Navigateしましたが,無理でした。

おかしいですね。
新規に、最低限のコードを記述したプロジェクトを作っても再現しますか?

うちでは

--ここから--
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;

namespace WindowsApplication1
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}

private void Form1_Load(object sender, EventArgs e)
{
this.webBrowser1.Navigate("http://hidori.jp/");
}
}
}
--ここまで--

という単純なコードで期待通りの動作をしています。

> Shownイベントがないんですが,何か宣言しなければならないのでしょうか?

開発環境は .NET 1.x ですか?
■No17714に返信(tororoさんの記事)

私の環境で、現在は下のコードだけで動作しています。

Public Class Form1
    Inherits System.Windows.Forms.Form

(Windows フォーム デザイナで生成されたコード)

    Private ie As New AxSHDocVw.AxWebBrowser
    Private Sub Form1_Load(ByVal sender As System.Object, _
                           ByVal e As System.EventArgs) Handles MyBase.Load
        ie.Size = New Size(600, 400)
        ie.Location = New Point(20, 20)
        Me.Controls.Add(ie)
        ie.Navigate("http://www.google.co.jp/")
    End Sub
End Class

ただ、最初はこれと同じようなコードで動作せず、下のように
NavigateをActivatedイベントハンドラに移すと動作しました。

Private Sub Form1_Activated(ByVal sender As Object, _
                            ByVal e As System.EventArgs) Handles MyBase.Activated
    Static firstCall As Boolean = True
    If firstCall Then
        ie.Navigate("http://www.google.co.jp/")
        firstCall = False
    End If
End Sub

そこで、「最初はLoadイベント時に呼んだから動作しなかったのだろう」と
思っていたのですが、もう一度NavigateをLoadイベントハンドラに戻してみると、
予想に反して動作したのは不思議な点です。

> Shownイベントがないんですが,何か宣言しなければならないのでしょうか?

.NET 2.0ならばShownイベントが使えますが、.NET 1.xにはShownイベントがないので、
上ではShownのかわりにActivatedを使い、初回以外はスルーしています。

もしかしたらtororoさんの環境で、Activated時にはNavigateできるということは
ないでしょうか。

あと、素人考えで恐縮ですが、Navigateの前に

Me.Show()
System.Threading.Thread.Sleep(適当な長さ)

を入れるなんていうのは、だめでしょうか。
2006/09/29(Fri) 12:34:10 編集(投稿者)

今まではAxWebBrowserのインスタンスをNo17728のように生成していましたが、フォームデザイナでツールボックスから貼り付けてみると、フォームデザイナが生成したコードの中に、初期化に関係ありそうなものがいろいろと入っていました。これらがないから動作しなかった(場合がある)のではないかという気もしますが、なくても動作することがあるというのも、不思議ではあります。
開発環境は1.1です。

Activedの後に,実施したのですが,無理でした。
また,Sleepで,時間待機したのですが,同様のエラーが発生しました。

既存のアプリケーションにて,実施しているので,シンプル(はじめから)に検証しようとしたところ,AxSHDocVw.AxWebBrowserが定義されていませんとなってしまいます。???何かimports/参照,必要でしたかね?
いま,ここで,つまづいています。報告まで。


■No17728に返信(千八巧者さんの記事)
> ■No17714に返信(tororoさんの記事)
>
> 私の環境で、現在は下のコードだけで動作しています。
>
> Public Class Form1
> Inherits System.Windows.Forms.Form
>
> (Windows フォーム デザイナで生成されたコード)
>
> Private ie As New AxSHDocVw.AxWebBrowser
> Private Sub Form1_Load(ByVal sender As System.Object, _
> ByVal e As System.EventArgs) Handles MyBase.Load
> ie.Size = New Size(600, 400)
> ie.Location = New Point(20, 20)
> Me.Controls.Add(ie)
> ie.Navigate("http://www.google.co.jp/")
> End Sub
> End Class
>
> ただ、最初はこれと同じようなコードで動作せず、下のように
> NavigateをActivatedイベントハンドラに移すと動作しました。
>
> Private Sub Form1_Activated(ByVal sender As Object, _
> ByVal e As System.EventArgs) Handles MyBase.Activated
> Static firstCall As Boolean = True
> If firstCall Then
> ie.Navigate("http://www.google.co.jp/")
> firstCall = False
> End If
> End Sub
>
> そこで、「最初はLoadイベント時に呼んだから動作しなかったのだろう」と
> 思っていたのですが、もう一度NavigateをLoadイベントハンドラに戻してみると、
> 予想に反して動作したのは不思議な点です。
>
>>Shownイベントがないんですが,何か宣言しなければならないのでしょうか?
>
> .NET 2.0ならばShownイベントが使えますが、.NET 1.xにはShownイベントがないので、
> 上ではShownのかわりにActivatedを使い、初回以外はスルーしています。
>
> もしかしたらtororoさんの環境で、Activated時にはNavigateできるということは
> ないでしょうか。
>
> あと、素人考えで恐縮ですが、Navigateの前に
>
> Me.Show()
> System.Threading.Thread.Sleep(適当な長さ)
>
> を入れるなんていうのは、だめでしょうか。
いろいろ的外れなことを書いてしまったようですみません。
シンプルにはじめから試すには、次のようにすればいいかと思います。

1. 新しいプロジェクトを作る。

2. ツールボックスの「Windowsフォーム」が開いた状態で「Windowsフォーム」を右クリック、「アイテムの追加と削除」を選ぶ。

3. 「COMコンポーネント」の「Microsoft Web Browser」をチェックしてOK。

4. ツールボックスに追加された「Microsoft Web Browser」をフォーム上にドラッグ。

5. フォームのLoadイベントハンドラに、「AxWebBrowser1.Navigate(...)」を追加。
いろいろ,ありがとうございます。

シンプルに検証することができましたが,Activedで,やはり同じエラーが発生しました。バージョンの違いでしょうか?1.1では不可?
??????????????

Public Class Form1
Inherits System.Windows.Forms.Form

Dim p_id As New AxSHDocVw.AxWebBrowser

Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load

End Sub


Private Sub Form1_Activated(ByVal sender As Object, ByVal e As System.EventArgs) Handles MyBase.Activated

Static firstCall As Boolean = True
If firstCall Then
p_id.Navigate("http://www.google.co.jp/")
firstCall = False
End If

End Sub
End Class
> シンプルに検証することができましたが,Activedで,やはり同じエラーが発生しました。バージョンの違いでしょうか?1.1では不可?

私も1.1です。フォームから貼りつけて動作したのでしたら、そのままそのスタイルではだめですか?
Activatedイベントを使うという選択肢については、どうやらあまり関係なかったようです。(^^ゞ

もし、(フォームデザイナで貼りつけるのではなく)明示的にインスタンスを生成するのであれば、
それなりの初期化コードが必要なのかと思いますが、そのあたりのことは私の知識を超えていますので、
お役に立てず申し訳ありません。
> シンプルに検証することができましたが,Activedで,やはり同じエラーが発生しました。バージョンの違いでしょうか?1.1では不可?

前に書いたと思いますが、Navigate() を行うべき適切なタイミングは Form.Load() イベントです。

(初回の)Form.Activate() では、おそらくブラウザコントロールの実体化が終わってないんじゃないかと思います。

問題は「ActiveX コントロールの初期化が行われているかどうか」なので、行き当たりばったりにコードの増減を行うのではなく、イベントハンドラの先頭に Debug.WriteLine() でも追加して、イベントの発生順序を確認しながら検討を進めた方がいいと思いますよ。
>もし、(フォームデザイナで貼りつけるのではなく)明示的にインスタンスを生成>するのであれば、
>それなりの初期化コードが必要なのかと思いますが、そのあたりのことは私の知識>を超えていますので、
>お役に立てず申し訳ありません。
いえいえ,ありがとうございます。フォームデザイナから貼り付けるとうまくいくのですが,インスタンス化すると無理です。(現状報告まで)

>前に書いたと思いますが、Navigate() を行うべき適切なタイミングは Form.Load() イベントです。
最初は,Loadで出来なかったので、疑問に思い、質問を投げさせて頂きました。その後、いろいろなイベント/方法で試したのですが,インスタンス化した場合は,どれも上手くいかない状態です。再度回答に目を通して頂き,ありがとうございます。
>いろいろなイベント/方法で試したのですが,インスタンス化した場合は,どれも上手くいかない状態です。再度回答に目を通して頂き,ありがとうございます。

「インスタンス化」とは、すべて自前のコードでブラウザコントロールを扱うことを意味していますよね?

その場合、(#region によって非表示になっている箇所も含めて)デザイナが自動生成したコードを参考にしていますか?

前に話題に上っていたような気がしますが、.NET 1.x レベルだとブラウザコントロールに対する初期化が必要だったように思います。
最初に、IEをnewでインスタンスを生成して
shellwindowsかなにかのコレクションを参照
では無理ですか?・・
Dim IEWindows As New SHDocVw.ShellWindowsClass
Dim Element As SHDocVw.InternetExplorer

ie.Navigate("http://www.google.co.jp")
ie.Visible = True

For Each element In IEWindows
Console.WriteLine(Element.LocationURL)
      'ここらへんで取得できるまでやる

Next

> 前に話題に上っていたような気がしますが、.NET 1.x レベルだとブラウザコン
>トロールに対する初期化が必要だったように思います。
なるほど・・では無理かな。

.Net 2005 からはじめたのでなんともいえませんが

'一応テストしてみました。これで動きますが。
Public Class Form1

Private Sub Form1_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
Dim ie As New SHDocVw.InternetExplorer
ie.Navigate("http://www.google.co.jp")
ie.Visible = True

End Sub
End Class
'.Net Framework 2.0,VB 2005 で動きました。
できた!!!!!

>その場合、(#region によって非表示になっている箇所も含めて)デザイナが自動生成したコードを参考にしていますか?
>前に話題に上っていたような気がしますが、.NET 1.x レベルだとブラウザコントロールに対する初期化が必要だったように思います。

自動生成されているコードを参考にしたらできました!!!
また,不思議なことに,一度できたので,どのコードが必要か検証しようとしたところ,Navigateだけになってしまいました。
プラットフォームでの初期化に一度完了してしまえばよいってことになっているのでしょうか?どれが,それに起因するのか分かりませんが,以下にコードをノッケテおきます。みなさま、ありがとうございました。

Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load

Dim resources As System.Resources.ResourceManager = New System.Resources.ResourceManager(GetType(Form1))
p_id = New AxSHDocVw.AxWebBrowser
CType(p_id, System.ComponentModel.ISupportInitialize).BeginInit()
Me.SuspendLayout()
'
'p_id
'
With p_id
.Enabled = True
.Location = New System.Drawing.Point(8, 48)
.OcxState = CType(resources.GetObject("p_id.OcxState"), System.Windows.Forms.AxHost.State)
.Size = New System.Drawing.Size(300, 150)
.TabIndex = 0
End With
'
'Form1
'
Me.AutoScaleBaseSize = New System.Drawing.Size(5, 12)
Me.ClientSize = New System.Drawing.Size(292, 273)
Me.Controls.Add(Me.p_id)
Me.Name = "Form1"
Me.Text = "Form1"
CType(Me.p_id, System.ComponentModel.ISupportInitialize).EndInit()
Me.ResumeLayout(False)

p_id.Navigate("http://www.google.co.jp/")

End Sub
解決済み!
「コードだけ」を参考にしないで、「コードを書くべき位置」も参考にしてください。

> p_id = New AxSHDocVw.AxWebBrowser
(略)

> Me.ResumeLayout(False)

までは、Form のコンストラクタの中、IDE が自動挿入した InitalizeComponents() 呼び出しの後等に配置するべきです。

DOBON.NET | プログラミング道 | プログラミング掲示板