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

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

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

Internet Explorer(IE;MSIE)はマイクロソフトが開発したウェブブラウザです。Microsoft Windowsに組み込まれています。

Visual Studio

Microsoft Visual StudioはMicrosoftによる統合開発環境(IDE)です。多種多様なプログラミング言語に対応しています。

VB.NET

Microsoft Visual Basic .NETのことで、Microsoft Visual Basic(VB6)の後継。 .NET環境向けのプログラムを開発することができます。 現在のVB.NETでは、.NET Frameworkを利用して開発を行うことが可能です。

Q&A

解決済

3回答

22075閲覧

VB.netでIE操作中に「HRESULT からの例外」エラーで止まる

ot2os

総合スコア23

Internet Explorer

Internet Explorer(IE;MSIE)はマイクロソフトが開発したウェブブラウザです。Microsoft Windowsに組み込まれています。

Visual Studio

Microsoft Visual StudioはMicrosoftによる統合開発環境(IDE)です。多種多様なプログラミング言語に対応しています。

VB.NET

Microsoft Visual Basic .NETのことで、Microsoft Visual Basic(VB6)の後継。 .NET環境向けのプログラムを開発することができます。 現在のVB.NETでは、.NET Frameworkを利用して開発を行うことが可能です。

0グッド

0クリップ

投稿2018/03/30 04:51

編集2018/04/02 08:14

いわゆるWebスクレイピングのようなことをやろうとしています。
IEウィンドウを操作して特定のWebサイト上で決まったメニュー操作を行い、表示された情報を取得する作業です。

実際に作成したコードを走らせると途中で**「HRESULT からの例外」**エラーが発生して処理が止まってしまいます。
このエラーへの対処法についての質問です。
エラー発生状況を以下に箇条書きします。

  • 全く同じ条件で同じコードを走らせても、エラーが出るときと出ない時がある。
  • エラーが出る箇所も毎回異なる。
  • 出るエラーも毎回異なる。
  • ただし、すべて「HRESULT からの例外:0x????????」形式のエラーで出ている(?は数字)
  • エラーが出てから再度[続行]で進めても同じエラーで先へ進めない(つまり実施タイミングの問題ではない?)

コードの一例を以下に記載します。(下記以外のコードでもエラーは出ます)

lang

1Option Explicit On 2 3Module Module1 4 Public Sub Main(ByVal targetURL As String) '引数に対象URLを入れて実施する 5 Dim objIE As Object 6 objIE = CreateObject("InternetExplorer.Application") 7 objIE.Visible = False '←★ここでエラーが出る場合もある。 8 objIE.navigate(targetURL) 9 10 Do '「次のページ」ボタンのループ 11 Call IEWait(objIE) 12 13 'ページ内の全要素検索 14 For Each one_tag In objIE.document.all 15 If UCase(one_tag.TagName) = UCase("a") Then 16 Debug.Print(one_tag.href) '該当リンクアドレスを取得 17 End If 18 Next 19 Loop While Ichiran_Tugihe(objIE) '「次のページ」ボタンを押す 20 21 'IE終了 22 objIE.Quit 23 objIE = Nothing 24 End Sub 25 26 27 'IEを待機する関数 28 Private Sub IEWait(ByRef objIE As Object) 29 Do While objIE.busy = True Or objIE.readystate <> 4 30 System.Windows.Forms.Application.DoEvents() 31 Loop 32 End Sub 33 34 '「次のページ」ボタンを押すスクリプト 35 Private Function Ichiran_Tugihe(ByRef objIE As Object) As Boolean 36 Dim i As Long 37 Ichiran_Tugihe = False 38 39 For i = 0 To objIE.document.links.length - 1 '←★追加情報:HRESULT からの例外:0x800A01B6エラーが出たりでなかったり 40 If objIE.document.links(i).title = "次のページ" Then 41 Ichiran_Tugihe = True 42 objIE.document.links(i).Click 'クリック 43 Call IEWait(objIE) 44 Exit For 45 End If 46 Next 47 End Function 48 49End Module 50

●発生するエラー:
上記コードで最もよく発生するエラーは下記です。

型 'System.NotSupportedException' のハンドルされていない例外が Microsoft.VisualBasic.dll で発生しました

追加情報:HRESULT からの例外:0x800A01B6

このエラーを控えた際はFor i = 0 To objIE.document.links.length - 1部分で発生していましたが、他の部分でも出たりでなかったりします。

上記より発生頻度は低い気がしますが、下記も出ます。

型 'System.Runtime.InteropServices.COMException' の例外が Microsoft.VisualBasic.dll で発生しましたが、ユーザー コード内ではハンドルされませんでした

追加情報:リモート プロシージャ コールに失敗しました。 (HRESULT からの例外:0x800706BE)

これはobjIE.Visible = Falseで出ました。

●試したこと:

  • Dim objIEdoc As mshtml.HTMLDocument = DirectCast(objIE.document, mshtml.HTMLDocument)を使って、objIEに対して実施していたコマンドをobjIEdocに置き換える

→ 心なしかエラー発生率は下がった気がしますが、やはり同様のエラーが出ることがあります。

  • Form上にWebBrowserオブジェクトを配置し、objIE = Form1.WebBrowser1コードを配置する

→ WebBrowserとIEの動作仕様が違うのか、JavaScript絡みのエラーダイアログが頻発してどのサイトも正常動作せず。

  • 各プロシージャ内にTry~Catchを使って無理やりエラー回避することは一応は可能です。

lang

1Dim Retry As Boolean = True 2Dim objIE As Object 3objIE = CreateObject("InternetExplorer.Application") 4 5Do While Retry = True 6 Try 7 ' 8 'ここに実施するコードを入れる。 9 ' 10 Retry = False 11 Catch ex As System.Exception 12 objIE.Quit 13 objIE = Nothing 14 objIE = CreateObject("InternetExplorer.Application") 15 End Try 16Loop

開発、テスト環境:
Win10x64 1709
Internet Explorer 11
Visual Studio Community 2015


補足です。

今回、エラーコードを基に調べてみたところ「原因はわからないけどこうすれば直った」と言う旨の話が何件かあり、それを基に**「●試したこと:」**を実施していますが、解決していません。

前述の通り、エラー発生時にエラーをcatchしてから再度同じ処理を実施すれば今度はエラーが出ずに継続できますが、何回かに一回、全く同じ場所で同じエラーが出続けて無限ループすることがあることがわかりました。

Form側のコードを下記のようにし、メインの処理をスレッドに分けて、一定期間処理が終わらなければ無理やりスレッドごと処理を中断し、その後再開すると言う方法を試してみました。しかし、この方法で処理を再実行しても全く同じ場所で同じエラーが出て進めません。

試しに[ielowutil]プロセスも終了するようにしてみましたが、同様でした。

しかし、手動で[デバッグの停止]を実施して、再度プログラムを開始して同じURLを処理すると正常に機能します。

lang

1Option Explicit On 2 3Public Class Form1 4 5 Private t As New System.Threading.Thread( 6 New System.Threading.ParameterizedThreadStart(AddressOf Main)) 7 8 Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click 9 10 LastAct = Now 11 Me.Timer1.Enabled = True 12 t.Start(Me.TextBox1.Text) '入力されたURL内のリンクを調べる 13 14 End Sub 15 16 '一定期間応答がなければ強制的にスレッドを立ち上げなおす 17 Private Sub Timer1_Tick(sender As Object, e As EventArgs) Handles Timer1.Tick 18 '10分以上応答なければ強制再実行 19 If DateDiff("n", LastAct, Now) > 10 Then 20 Me.Timer1.Enabled = False 21 Debug.Print("10分応答なし") 22 t.Abort() 23 t.Join() 24 KillProcess("iexplore") 'iexploreのプロセスを強制終了するコマンド 25 LastAct = Now 26 t = Nothing 27 t = New System.Threading.Thread( 28 New System.Threading.ParameterizedThreadStart(AddressOf Main)) 29 t.Start(Me.TextBox1.Text) 30 Me.Timer1.Enabled = True 31 End If 32 End Sub 33End Class

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

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

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

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

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

defghi1977

2018/03/30 05:05

こういう場合は「0x800A01B6」とか「0x800706BE」とかでググるのですよ
guest

回答3

0

ベストアンサー

「Webスクレイピングのようなこと」を行いたいのであれば、
WebBrowserの方が.Netで扱いやすいし、応用が利くし、
少なくとも今回のようなエラーは見たことがありません。
注意点として、WebBrowserは何もしなければIE7で動きますが、
WebBrowserで使用するIEのバージョンを上げることができるため、
古いIEに対応しないサイトでも応用できます。

例えば、以下サイトを参考にしてみてください。
https://www.ipentec.com/document/csharp-change-webbrower-control-internet-explorer-version

その他、「WebBrowser IE バージョン 変更」などでググると、色々とヒットします。


追記:
サンプルを作成してみました。
今回作成するサンプルアプリをWBTest.exeとします。
まず、レジストリエディタでHKEY_CURRENT_USER\Software\Microsoft\Internet Explorer\Main\FeatureControl\FEATURE_BROWSER_EMULATIONにWBTest.exeの情報を追加します。
(デバッグを行う際はWBTest.vshost.exeも登録します。)
レジストリエディタ

このアプリでは、Form1にWebBrowser1, Button1, Button2を配置します。
あとは、以下のようなコードを書いてみました。

VB.Net

1Public Class Form1 2 Private Sub WebBrowser1_DocumentCompleted(sender As Object, e As WebBrowserDocumentCompletedEventArgs) Handles WebBrowser1.DocumentCompleted 3 If e.Url = WebBrowser1.Url Then 4 MsgBox("読込完了") 5 End If 6 End Sub 7 8 Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click 9 WebBrowser1.Navigate("https://dictionary.goo.ne.jp/") 10 End Sub 11 12 Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click 13 WebBrowser1.Navigate("https://www.excite.co.jp") 14 End Sub 15End Class

このサンプルでは、WebBrowser1_DocumentCompletedイベントで、対象のURLの読込が終わったときにメッセージボックスを表示していますが、この時まではWebBrowserや表示ページのクリック等の操作はしない方が良いようです。
(読込途中のjsがスクリプトエラーになるかも知れない?)

とりあえず、このサンプルでスクリプトエラーは確認できませんでしたが、もしかしたら100%ではないかも知れません。
本来の目的とは無関係なスクリプトであれば、WebBrowser1のScriptErrorsSuppressedプロパティをTrueにすることが有効かも知れません。

投稿2018/04/03 08:11

編集2018/04/11 09:44
kenshirou

総合スコア772

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

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

ot2os

2018/04/09 06:40

ありがとうございます。 ご提示いただいた手順でユーザーエージェントのバージョンは変わったようですが、やはり同様にJavaScript絡みのエラーが頻発して動きません。 ちなみに、デバッグだとユーザーエージェントのバージョンが反映しないようなので、一旦exeをビルドしてから試しています。 いただいたURLを参考にいろいろと試してみます。
kenshirou

2018/04/10 05:50 編集

ちなみに、作成した実行ファイルがxxx.exeの場合、開発環境でデバッグしながら動作させる場合には、デバッグ時に実行されるxxx.vshost.exeをレジストリに登録する必要があります。 あと、JavaScript絡みのエラーとありますが、Navigateしたページの読み込みが完了した状態でページ内操作(リンクのクリック等)を行っていますか? また、ページ読込完了はどのような方法で確認していますか?
ot2os

2018/04/10 07:09

ありがとうございます。 デバッグ時はxxx.vshost.exeですね。初歩的なことですみません。 (レジストリには0x2af9で登録試しています) ページ読み込みが完了するまでの待機はコード内のIEWaitにて行っています。 下記の条件の間、ずっとDoEventsで待機する方式をとっています。 objIE.busy = True Or objIE.readystate <> 4 さらに調べてみると、このDoEventsループ中にJavaScript絡みのエラーがいくつも出ている状態でしたので、ページ読み込み完了待ち自体はできているようです。 エラーはよくある下記のウィンドウのもので、IEをCreateObjectして操作した場合はこのエラーは出ません。 (x部分はURL) > スクリプトエラー > このページのスクリプトでエラーが発生しました。 > ライン:0 > 文字:0 > エラー:Script error. > コード:0 > URL: https://xxxxxxxxx.js > このページのスクリプトを実行し続けますか?
kenshirou

2018/04/11 00:52 編集

WebBrowserを使用する場合、ページ読込完了の判断にはDocumentCompletedイベントを使用します。 DoEventsでのループは意図せぬことが発生するかも知れません。 ※詳細は、WebBrowser DocumentCompletedでググってみてください。 私はこの方法で、古いIEでうまく表示できないサイトも含め、様々なWebサイトのクロールが問題なく行えていましたが、もしかしたら、私の知り得ない点が潜んでいるかも知れません。 差し支えなければ、問題の発生するURLを教えてもらえませんか? ちなみに、機械的なアクセスを禁止しているような所であれば、申し訳ないのですがお力になれないかも知れません。悪しからず。
ot2os

2018/04/11 03:07

度々ありがとうございます。 該当のエラーですが、Navigateコマンドのみを実施するSubを作成して実施しても、やはり読み込み中に発生してしまいます。 発生するサイトは複数ありますが、試してみたところ一般に誰でもアクセスできるサイトで確実にエラーが出るのは下記サイトでした。 https://www.excite.co.jp https://dictionary.goo.ne.jp ちなみに、下記サイトでユーザーエージェントを確認してみました結果も記載します。 http://www.openspc2.org/JavaScript/library/system/useragent/ ユーザーエージェント: Mozilla/5.0 (Windows NT 6.2; WOW64; Trident/7.0; rv:11.0) like Gecko
kenshirou

2018/04/11 04:11

URLの提供ありがとうございます。 こちらでも確認してみます。(ただし、お時間をください。)
kenshirou

2018/04/11 09:44

元の回答にWebBrowserの使用例を追記しました。
ot2os

2018/04/13 06:47 編集

わざわざ検証までしていただいてありがとうございます。 こちらでも同じことを試してみたのですが、やはりなぜかエラーが出てしまいます。 ちなみに、 https://www.excite.co.jp では「https://pagead2.googlesyndication.com/pagead/show_ads.js」 https://dictionary.goo.ne.jp では「https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js」 のURLのjsがエラーでした。 しかし、Navigateの前に下記1行を入れるとエラーが出なくなりました。 WebBrowser1.ScriptErrorsSuppressed = True objIEをそのままWebBrowserに入れ替えると、ところどころメソッドやプロパティが違ってうまく動かないので、調べながら引き続き検証してみます。
kenshirou

2018/04/13 09:48

やはり、WebBrowser1.ScriptErrorsSuppressed = Trueを入れないとスクリプトエラーが出ましたか。スミマセン。 ScriptErrorsSuppressedプロパティはスクリプトエラー等のダイアログを表示しない目的で使用するため、非表示のスクリプトエラーが原因で、本来の目的とする機能が動作しない恐れもあります。 その場合は、もしかしたら今までのIEの外部処理での対応を検討した方がいいかも知れません。(お役に立てなくてゴメンナサイ。)
guest

0

そもそも論になりますが、スクレイピングに依存したシステム自体、不完全と気付くべきですね。
相手のシステムに変更があれば動かなくなるんですから。

投稿2018/04/18 03:47

tekka

総合スコア514

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

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

0

IEを外部から操作する処理はSeleniumのIE用のWebDriverが参考になります。
安定して動作させるにはいくつか注意点があるので、同じことを実施してみてはどうでしょうか?
ページ遷移をする場合は、保護モードの設定を統一しないと別プロセスが生成される場合があるので重要です。

参考リンク
Required Configuration
(2)IEの設定

あと気になる点は

  • Mainに<STAThread>がない
  • System.Windows.Forms.Application.DoEvents()は普通のSleepだと問題あるのか?

投稿2018/04/04 14:43

hmmm

総合スコア818

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

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

ot2os

2018/04/10 05:28

ありがとうございます。 下記2点試してみましたが、やはり状況変わりませんでした。 ・<STAThread>の追記 ・DoEvents()をSleep(200)に変更 追記部分では回避策としてMainの処理をスレッドにして走らせ、一定時間処理が進まなければ無理やりAbortで処理を中断するようにしています。 (処理が成功するたびにLastAct変数に現在時刻を書き込んでいます) 再度Mainの処理がStartされた際に同じエラーで進まないのに、手動でデバッグを終了して再度同じURLを指定して開始するとなぜか正常に進みます。 スレッドをAbort、再Startする処理とどこが違うのかよくわからず。 見る限り、Start後の処理もちゃんとMainの最初から走っているように見えます。 この処理がうまく行けばひとまずの回避はできそうですが、別途Seleniumも検討してみます。
hmmm

2018/04/12 11:20

私が重要だと思ったのはRequired Configurationのリンク先に記載されたのIEの設定です。 例えば、IEはマルチプロセスで動作するため、同一Window内でのページ遷移の場合でも別プロセスとなる可能性があります。そうなると正しく操作できません。 保護モードの設定をすべて統一することでそれを抑止することが出来ます。 そんな感じでいろいろとノウハウがあるのでリンク先の説明を見てIEの設定を変更しないとまともに動きません。
ot2os

2018/04/18 02:55

ありがとうございます。 今いろいろな条件で検証中ですが、資料に従ってIEのすべてのゾーンで保護モードを統一したところ、エラーの発生率はだいぶと下がった気がします。(同様のエラー自体は発生します) 引き続きいろいろ検証してみます。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問