複数起動させたIEのイベントを拾うには


かわう  2005-11-18 21:13:42  No: 92765

Dim IE(3)
For i=0 To 3
  Set IE(i) = WScript.CreateObject("InternetExplorer.Application","IE" & Cstr(i) & "_")
Next

上記のようにして複数のIEを起動して処理をかけたいのですが、
各IEのイベントの拾い方が分かりません。
配列でない場合は、

Sub IE_OnQuit  や Sub IE_DocumentComplete で拾えると思うのですが、
配列の場合どうすればよいのでしょうか?
よろしくお願いします。


あん  2005-11-19 06:38:44  No: 92766

IEの起動やイベントをクラスに記述します。
クラスを配列で宣言すればOKだよ。


かわう  2005-11-20 00:58:32  No: 92767

1個目を起動
  1個目の処理
1個目の処理がまだおわっていない状態で2個目を起動
  1個目の処理は途中で止まる
  2個目の処理が始まる
  2個目の処理が終わったら1個目の処理が途中から始まる

上記のような動きになってしまいます。
スレッド処理をつかえばいいのでしょうか?


あん  2005-11-20 02:43:16  No: 92768

ソースがあれば何かアドバイスできるかも


あん  2005-11-20 03:25:09  No: 92769

あと

>1個目を起動
>  1個目の処理
:
:

これって
複数起動させたIEのイベントを拾うには
には関係ないように思えます。

ソースを見れば関係がわかるのかな


かわう  2005-11-21 03:53:54  No: 92770

最初の質問者です。
二回目の「かわう」の発言は私になりすました別の人です。

あんさんご返答ありがとうございます。
実はVBScriptなんですが、クラスによる記述とは
具体的にどのように記述すればよいのでしょうか?

サンプル等ありましたら見せてもらえると助かります。
よろしくお願いします。


あん  2005-11-21 05:03:02  No: 92771

>Sub IE_OnQuit  や Sub IE_DocumentComplete で拾えると思うのですが、
とあるので配列でない場合のソースを提示してください。
1から作るのは大変です。


ヤマ@睡眠不足  2005-11-21 12:19:30  No: 92772

'プロシージャ
For i = 0 To 3
Set IE(i) = New IEClass
'    IE(i).Init
    IE(i).Navigate "http://www.yahoo.co.jp/"
    
Next

'======================モジュール
Public IE(3) As Object
'=================IEClassという名前のクラスを作ってそこ============-

Public WithEvents IE As InternetExplorer

Private Sub Class_Initialize()
    Set IE = CreateObject("InternetExplorer.Application")

End Sub

Public Sub IE_DocumentComplete(ByVal pDisp As Object, URL As Variant)
IE.Visible = True

MsgBox URL
End Sub
Public Sub Navigate(URL As String)
IE.Navigate2 URL

End Sub
Property Let Visible(blnVisbible As Boolean)
IE.Visible = blnVisible
End Property
'======================
みたいな感じでコード書いて見ました。

あんさん、もし変なところがあればご指摘お願いします。

一応このコードだと、
クラスでIEのイベント配列型毎にを拾えますよ?(日本語が変だな。。)


ヤマ@睡眠不足  2005-11-21 12:21:21  No: 92773

えっと、プロジェクトからコンポーネントで
Internet Controlを選択するとエラーになると思うので
参照設定からMicrosoft Internet Controlsを選択してください。


あん  2005-11-21 14:17:43  No: 92774

ヤマ@睡眠不足さん
こういうソースを待ってました。
でもVBとVBAだと動くんですが(私はVBAで確認しました)
VBScriptだとWithEventがないので
クラス化しても意味がないことがわかりました。
クラス化してもクラスの中のイベントが動きませんでした。

イベントの登録の仕方が違うみたいです。
一応以下のソースでイベントは拾えてます。
Dim IE(3)
For i=0 To 3
    Set IE(i) = WScript.CreateObject("InternetExplorer.Application","IE_")
Next

msgbox "WAIT"

Sub IE_OnQuit()
  msgbox "QUIT"
End Sub

値によって振り分けをしたい場合は
IEオブジェクトのプロパティを使用するか
イベントを動的に作成する必要があります。
こんな感じ
Dim IE(3)
For i=0 To 2
  Set IE(i) = WScript.CreateObject("InternetExplorer.Application","IE" & Cstr(i) & "_")
  IE(i).Visible=true
  AA = AA & "Sub IE" & Cstr(i) & "_OnQuit() : "
  AA = AA & "idx = " & Cstr(i) & " : "
  AA = AA &  "msgbox ""QUIT"" & idx"  & " : "
  AA = AA &  "End Sub " & " : "
Next

Execute AA

msgbox "WAIT"

今回は色々勉強になりました^^


かわう  2005-11-21 22:17:29  No: 92775

あんさん、ヤマ@睡眠不足さんありがとうございます。

あんさんの仰る通り、IE_〜でイベントを取得できました。
振り分けはSetPropertyとGetPropertyを使用して振り分けられそうです。

そこで何度も質問ばかりで申し訳ないのですが、下記のようなスクリプトを組んだ場合
各IEオブジェクト間(?)でスレッドセーフにするような仕組みが必要になるのでしょうか?
ほとんど同じタイミングで同じ関数を使用したりすると思うのですが。

よろしくお願いします。

Dim complete(3)
Dim IE(3)
For i=0 To 3
    Set IE(i) = WScript.CreateObject("InternetExplorer.Application","IE_")
    IE(i).SetProperty "ID", i
    IE(i).Visible = True
  startNavigate IE(i)
Next

Sub IE_DocumentComplete(pdisp,surl)
  
  msgbox pdisp.GetProperty("ID")
  
End Sub

Sub startNavigate(objIE)
  
  Dim intID
  intID = objIE.GetProperty("ID")
  
  objIE.Navigate strURL
  
  complete(intID) = False
  Do Until complete(intID) = True
    WScript.Sleep 1000
  Loop
  complete(intID) = False
  
  :
  :
  
End Sub


魔界の仮面弁士  2005-11-21 23:04:40  No: 92776

Sleepのせいで並列動作になっていないような気もしますが、
それはとりあえず置いといて……。

> SetPropertyとGetPropertyを使用して
「PutProperty」と GetProperty なのでは?

http://msdn.microsoft.com/workshop/browser/webbrowser/reference/objects/internetexplorer.asp


かわう  2005-11-21 23:22:48  No: 92777

>Sleepのせいで並列動作になっていないような気もしますが、
>それはとりあえず置いといて……。
WScriptでSleepすると並列動作にはならないんでしょうか?
Navigate後、DocumentCompleteを待つ処理を並列処理する場合どうすれば良いのでしょうか・・・?(;;

>> SetPropertyとGetPropertyを使用して
>「PutProperty」と GetProperty なのでは?
すいません、書き間違えてしまいました。


ヤマ@不眠  2005-11-22 12:41:51  No: 92778

GetPropertyなど難しいの使ってますが、、
IE(i).tag=i
タグプロパティに格納したらどうでしょうか?
VBscriptで使えるかわかりませんが、、
後は Sleep 1000はまずいと思います。VBSはよくわかりませんが、
DoEvents
Sleep 10'CPU使用率が高くなるとまずいので入れてます  好みかな?
で良いと思います。
Sleepにしちゃうと確か自プログラムの他の処理が行われないです。
のでDoEventsで自アプリの動作ができるようにして、
sleep 10くらいで他のアプリにも動作させてあげてください。
(?ここらへんはよくわからんのですが)
私はこうかいておりますです。


ヤマ@ねむ  2005-11-22 13:26:13  No: 92779

えっと、
>ほとんど同じタイミングで同じ関数を使用
ですが
同じファイルや、変数にアクセスしてたりすると
変なことになりますが、別に大丈夫だと思います。
(良い例が再帰的(自分で自分を呼ぶ)に関数呼び出すやつとか、スタックオーバーフローになったりしますが)

で、MSDNにのってたような気もしますが
もうちょっとdocumentオブジェクトにアクセスするできるようになるまで
厳密に処理使用と思ったらこんな感じだと思います。

'======================-
 Dim iCOunt
 Do While True
   If (objIE.readyState > READYSTATE_INTERACTIVE) Then
If (objIE.document.readyState = "interactive") Or _
                (objIE.document.readyState = "complete") Then
              'ここにDocumentを使った処理かいてください
               msgbox objIE.locationTitle'とか
              Exit do

     End  if
  end if

    doevents
    sleep 500'0.5秒

       iCOunt = iCOunt + 1
       If iCOunt > val(30) * 2 Then'30秒でタイムアウトとすると
          'タイムアウト処理かいてください
          Exit Do
        End If

Loop

'==============
参考になれば。。。いいんですが。。


かわう  2005-11-22 21:13:18  No: 92780

ヤマさん寝不足のところ(?)ありがとうございます。

調べてみましたが、VBScriptではDoEventsはサポートされていないようです。
http://support.microsoft.com/kb/190273/en-us
情報が古いのでリファレンスも見ましたが、DoEventsはありませんでした。

そこでヤマさんのコードを参考にさせて頂いて、とりあえずスリープ処理は無しで、
IE.ReadyStateとIE.Busyの値をループ中で参照させてみようと思います。


ヤマ@文系  2005-11-26 12:18:39  No: 92781

Do Until complete(intID) = True
        WScript.Sleep 1000
    Loop

do while objIE.busy'=trueなくてもよい
loop

でいいかんじですね。
DHTMLの知識がなんか必要になってきたりしますが
がんばってください。
あんまり深い参照だとエラーになったりするのは仕様なのかな。。
ie.document.body.innterhtml
くらいまではOKなのかな。。?

ブラウザを制御できるといろいろできて楽しいですよね。
(お仕事だと楽しくないのかな。。)
ではでは。


※返信する前に利用規約をご確認ください。

※Google reCAPTCHA認証からCloudflare Turnstile認証へ変更しました。






  このエントリーをはてなブックマークに追加