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 で拾えると思うのですが、
配列の場合どうすればよいのでしょうか?
よろしくお願いします。
IEの起動やイベントをクラスに記述します。
クラスを配列で宣言すればOKだよ。
1個目を起動
1個目の処理
1個目の処理がまだおわっていない状態で2個目を起動
1個目の処理は途中で止まる
2個目の処理が始まる
2個目の処理が終わったら1個目の処理が途中から始まる
上記のような動きになってしまいます。
スレッド処理をつかえばいいのでしょうか?
ソースがあれば何かアドバイスできるかも
あと
>1個目を起動
> 1個目の処理
:
:
これって
複数起動させたIEのイベントを拾うには
には関係ないように思えます。
ソースを見れば関係がわかるのかな
最初の質問者です。
二回目の「かわう」の発言は私になりすました別の人です。
あんさんご返答ありがとうございます。
実はVBScriptなんですが、クラスによる記述とは
具体的にどのように記述すればよいのでしょうか?
サンプル等ありましたら見せてもらえると助かります。
よろしくお願いします。
>Sub IE_OnQuit や Sub IE_DocumentComplete で拾えると思うのですが、
とあるので配列でない場合のソースを提示してください。
1から作るのは大変です。
'プロシージャ
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のイベント配列型毎にを拾えますよ?(日本語が変だな。。)
えっと、プロジェクトからコンポーネントで
Internet Controlを選択するとエラーになると思うので
参照設定からMicrosoft Internet Controlsを選択してください。
ヤマ@睡眠不足さん
こういうソースを待ってました。
でも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"
今回は色々勉強になりました^^
あんさん、ヤマ@睡眠不足さんありがとうございます。
あんさんの仰る通り、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
Sleepのせいで並列動作になっていないような気もしますが、
それはとりあえず置いといて……。
> SetPropertyとGetPropertyを使用して
「PutProperty」と GetProperty なのでは?
http://msdn.microsoft.com/workshop/browser/webbrowser/reference/objects/internetexplorer.asp
>Sleepのせいで並列動作になっていないような気もしますが、
>それはとりあえず置いといて……。
WScriptでSleepすると並列動作にはならないんでしょうか?
Navigate後、DocumentCompleteを待つ処理を並列処理する場合どうすれば良いのでしょうか・・・?(;;
>> SetPropertyとGetPropertyを使用して
>「PutProperty」と GetProperty なのでは?
すいません、書き間違えてしまいました。
GetPropertyなど難しいの使ってますが、、
IE(i).tag=i
タグプロパティに格納したらどうでしょうか?
VBscriptで使えるかわかりませんが、、
後は Sleep 1000はまずいと思います。VBSはよくわかりませんが、
DoEvents
Sleep 10'CPU使用率が高くなるとまずいので入れてます 好みかな?
で良いと思います。
Sleepにしちゃうと確か自プログラムの他の処理が行われないです。
のでDoEventsで自アプリの動作ができるようにして、
sleep 10くらいで他のアプリにも動作させてあげてください。
(?ここらへんはよくわからんのですが)
私はこうかいておりますです。
えっと、
>ほとんど同じタイミングで同じ関数を使用
ですが
同じファイルや、変数にアクセスしてたりすると
変なことになりますが、別に大丈夫だと思います。
(良い例が再帰的(自分で自分を呼ぶ)に関数呼び出すやつとか、スタックオーバーフローになったりしますが)
で、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
'==============
参考になれば。。。いいんですが。。
ヤマさん寝不足のところ(?)ありがとうございます。
調べてみましたが、VBScriptではDoEventsはサポートされていないようです。
http://support.microsoft.com/kb/190273/en-us
情報が古いのでリファレンスも見ましたが、DoEventsはありませんでした。
そこでヤマさんのコードを参考にさせて頂いて、とりあえずスリープ処理は無しで、
IE.ReadyStateとIE.Busyの値をループ中で参照させてみようと思います。
Do Until complete(intID) = True
WScript.Sleep 1000
Loop
を
do while objIE.busy'=trueなくてもよい
loop
でいいかんじですね。
DHTMLの知識がなんか必要になってきたりしますが
がんばってください。
あんまり深い参照だとエラーになったりするのは仕様なのかな。。
ie.document.body.innterhtml
くらいまではOKなのかな。。?
ブラウザを制御できるといろいろできて楽しいですよね。
(お仕事だと楽しくないのかな。。)
ではでは。
ツイート | ![]() |