Sub DomSampleErr()
'IEをExcelから起動し、Excelから制御した状態にします
Dim objIE As New InternetExplorer
'エラー対策の開始
On Error GoTo ErrIE
objIE.Visible = True
'エラー対策の終了
On Error GoTo 0
Dim url As String
url = "http://www.exvba.com/ws/domformradio.html?time=" & Format(Now, "yymmddhhnnss")
'↑Cacheからのデータ取得になるのを嫌い、都度、違うURLになるようにした
'テストページを、IDで読み込みます
objIE.navigate url
'コンテンツ内の所定のオブジェクトを取得途中の処理記載略
Exit Sub
ErrIE:
Set objIE = Nothing
IE_kill 'すべてのIEを強制終了
MsgBox "エラーのため、すべてのIEを強制終了しました。"
End Sub
'参考サイト:EXCEL VBA プロセスのKILL
'http://chaser-news.com/archives/77
Private Sub IE_kill()
Dim strProcName As String '終了するプロセス名
Dim objProcList As Object 'プロセス一覧
Dim objProcess As Object 'プロセス情報
Dim lngKillNum As Integer '終了したプロセス数
strProcName = "iexplore.exe": lngKillNum = 0
On Error Resume Next
Set objProcList = GetObject("winmgmts:").InstancesOf("win32_process")
For Each objProcess In objProcList
If LCase$(objProcess.Name) = strProcName Then
objProcess.Terminate
If Err.Number = 0 Then
lngKillNum = lngKillNum + 1
Else
Debug.Print "エラー: " & Err.Description
End If
End If
Next objProcess
On Error GoTo 0
Set objProcList = Nothing
End Sub
Option Explicit
Public Sub ie_error_sample()
'Required: Microsoft Internet Controls
Dim objIE As New InternetExplorer
On Error Resume Next
objIE.Visible = True '[1]
If Err.Number <> 0 Then
Debug.Print Err.Number & vbTab & Err.Description
If Err.Number = -2125463506 Then
IE_kill
objIE.Visible = True '[2] [1]でしくじった visible = true に再トライ
End If
End If
Dim url As String
url = "http://www.exvba.com/ws/domformradio.html"
objIE.navigate url
'[3] 表示完了を待つ(問題の再現には最低限これが必要そう)
Do While objIE.readyState <> READYSTATE_COMPLETE Or objIE.Busy = True
DoEvents
Loop
objIE.Quit 'テスト実行上面倒なので都度自動的に終了することにした
End Sub
Private Sub IE_kill()
'Required: Microsoft WMI Scripting V1.2 Library
Dim procCollection As SWbemObjectSet 'プロセスのコレクション
Dim proc As SWbemObjectEx '個々のプロセス
Const S_PIE As String = "iexplore.exe"
On Error Resume Next
Set procCollection = GetObject("winmgmts:").InstancesOf("win32_process")
For Each proc In procCollection
If LCase$(proc.Name) = S_PIE Then '[*]
proc.Terminate
If Err.Number = 0 Then
Debug.Print "KILL OK"
Else
'For文に入った段階では存在したIEのプロセスが .terminate を実行する前に消えた、ということはあり得るかも
'たとえば、「[*]にブレークポイントを入れてこのマクロを止め、しばらく放置していた」等
Debug.Print "KILL NG:" & Err.Number & vbTab & Err.Description
MsgBox "KILL NG:" & Err.Number & vbNewLine & Err.Description
End If
End If
Next proc
On Error GoTo 0
Set procCollection = Nothing
End Sub
受講生さんの投稿
(投稿ID: 4445) 添付ファイルのダウンロード権限がありません
「05_IE制御してコンテンツを取得.xls」ファイル中にある、マクロを実行したのですが、最初の数回は正常に実行できるのですが、繰り返すと「objIE.Visible = True」のところでプログラムがストップします。原因がわからず、困っています。「オートメーションエラー」と書いてあります。助けてください。
ちなみに、再起動して再度マクロを実行しても、同じ症状がでます。
回答よろしくおねがいします。
小川 慶一さんのコメント
(コメントID: 6116)
おはようございます。
状況確認しました。
OSのバグぽいですね。
エクセルという安全地帯を超えて作業をするプログラムを書こうとすると、どうしても、こういうことは起こります。
ある意味、着実に技術向上しているからこそこういう問題に出会えるということでもあります。
問題の再現方法、原因、対策について、以下の動画にまとめました。
OS側でいずれ修正が入るのでは?とは思いますが...。それまでは、以下に示すように、腕力で対処しましょう。
https://www.dropbox.com/s/3ej5fh08e1c44nv/IE_Automation_Error.mp4?dl=0
ひきつづきよろしくお願いいたします。
> 質問です。
> 「05_IE制御してコンテンツを取得.xls」ファイル中にある、マクロを実行したのですが、最初の数回は正常に実行できるのですが、繰り返すと「objIE.Visible = True」のところでプログラムがストップします。原因がわからず、困っています。「オートメーションエラー」と書いてあります。助けてください。
>
> ちなみに、再起動して再度マクロを実行しても、同じ症状がでます。
> 回答よろしくおねがいします。
田中 宏明さんのコメント
(コメントID: 6117)
こんにちは。
IEは原因不明のエラーがよく起こり、原因を特定できないケースがほとんどです。
小川先生の動画解説をヒントに、すべてのIEを強制終了する対策を書いててみました。
(私の環境では、「オートメーションエラー」が再現しないので、これで解決できなかったら、すみません。)
> 繰り返すと「objIE.Visible = True」のところでプログラムがストップします。原因がわからず、困っています。「オートメーションエラー」と書いてあります。助けてください。
受講生さんのコメント
(コメントID: 6118)
サンプルコードまでいただきありがたいです。
自分のせいではなく、OSのエラーであれば一安心ということで・・・腕力でなんとかします!!!
小川 慶一さんのコメント
(コメントID: 6120)
おはようございます。
>田中さん
ありがとうございます。
再現には表示完了を待つことが必要そうな雰囲気です。(ie_error_sample 内の [3] )
エラーの詳細を調べ、期待するエラーの場合のみ IE_KILL に進むようにしてみました。
より丁寧にやるならそのほかのエラーの場合は云々、とかまで書くべきではありますが。
変数名も(ウチの講座受講生向けに)趣旨が分かりやすいものにリファクタリングしました。
あと、変数宣言時に Object型を使うのは好みでないので、先にライブラリを読み込んで、型を明示してみました。
(そのほかもいろいろあり、もはや原型あまりとどめてないので、参考リンクも削除)
こういうリファクタリングをするときの僕の作業の流れは、だいたい、以下です。
[1] まずは Object型で書いて動作確認してみる
[2] 変数に参照設定が無事に入ってから、 Typename関数で固有オブジェクト型の型名を調べる
[3] As Object の Object の部分を [2] で取得とした文字列にリライトしてみる
[4] [3]で動けばもうけもの。ダメなら、[2]で調べた文字列をネット等で検索
[5] 参照すべきライブラリをネットで見つける
[6] 参照すべきライブラリへの参照設定をする
[7] [6]でうまく動けばもうけもの。ダメなら、諦めて As Object に戻す
ということで、以下。
当初ご質問された受講生さんにとっても、かなり処理の全体像が分かりやすくなったかな、とも。
田中 宏明さんのコメント
(コメントID: 6123)
参照すべきライブラリを見つける方法は大変参考になります。
あちこちからコレクションしたマクロが手元にたくさんあるので、実験してみます。
> こういうリファクタリングをするときの僕の作業の流れは、だいたい、以下です。
> [1] まずは Object型で書いて動作確認してみる
> [2] 変数に参照設定が無事に入ってから、 Typename関数で固有オブジェクト型の型名を調べる
> [3] As Object の Object の部分を [2] で取得とした文字列にリライトしてみる
> [4] [3]で動けばもうけもの。ダメなら、[2]で調べた文字列をネット等で検索
> [5] 参照すべきライブラリをネットで見つける
> [6] 参照すべきライブラリへの参照設定をする
> [7] [6]でうまく動けばもうけもの。ダメなら、諦めて As Object に戻す