• ベストアンサー

Cygwin RubyでのIE

Cygwin上でRuby言語でInternetExplorerのプログラムを書いています 現在は 1、win32oleでIEを開く 2、プログラム内でhtmlでHPを作成し、IEで開く 3、2をプログラムを終了させるまで続ける といったものですが、2でURLを習得し、IEで開こうとすると新しい窓(ウィンドウ)が開いてしまいます。新しい窓(ウィンドウ)を開かずに、1で開いたIEを更新させたいです。 または、前に開いたページを閉じて、新たなページを開く。 win32oleやwin32APIなど、Cygwin上のRubyで使える方法ならいいので、ご存知の方いましたらお願いします。

質問者が選んだベストアンサー

  • ベストアンサー
回答No.5

sleep 1 while @@ie.Busy == true のsleepが失敗するのは、どこかでsleepメソッドを定義してしまっていることが原因ではないかと思います。 おそらく、 Kernel.sleep 1 while @@ie.Busy == true を使うことで解決するのではないかと思います。 (Kernel.sleepを再定義していればどうにもなりませんが。)

その他の回答 (4)

回答No.4

#3の補足、拝見しました。 どうやら、IEインスタンスを複数生成しているようですね、#3補足のプログラムでは WIN32OLE.new("InternetExplorer.Application") が複数回実行されますよ。 initializeメソッドの中とWIN32OLE.newの後ろに puts "test xxx" 等を入れて、いつ起動するか観察してたりすると、どのようにプログラムが動くか分かるようになると思います。 さて、最初のプログラムの問題点ですが、 IEクラスのインスタンスを複数作る(IE.newを複数実行する)のであれば、 その都度、インスタンス変数である @ie_ole @on も新しく作られますので、意図しない動作となってしまいます。 詳しくは 定数と変数 http://doc.okkez.net/static/191/doc/spec=2fvariables.html クラス変数の概念 http://www.rubylife.jp/ini/class/index8.html インスタンス変数の概念 http://www.rubylife.jp/ini/class/index4.html クラス変数・クラスメソッド http://www.mapee.jp/ruby/post_14.html 等を参照してください。 @ie_ole @on 等のインスタンス変数はnewや補足プログラムのopenを実行すると、古いものとは別に新しいものが生成されます。 @ie_ole と @on をそれぞれ、 クラス変数にの@@ie_ole と @@on に変更すると、インスタンス生成(new)を何回実行しても前の物を参照可能となります。 それと、openメソッドで newを使うことも問題です。 @ie_ole = IE.new(fullscreen = false) @ie_ole.web(~~~.html) の部分で、新しくIEのインスタンスを作ってしまうと、インスタンス変数も新しく作成されてそちらを使うので、意図しない動作となってしまいます。 self.web(~~~.html) のみとするのが意図した動作ではないかと思うのですが。 もくしは、クラスメソッドとして def IE.open ie = IE.new(fullscreen = false) ie.web(~~~.html) return ie end に変更して、IE.openで実行することで意図したメソッドになるかもしれません。(上記のクラスメソッドのリンクを参照してください) 2番目のプログラムも、openは1番目と同じ問題を抱えていて、さらにwebメソッドのie変数はローカル変数(上記定数と変数のリンクを参照してください)となっていて、メソッドを実行するたびに新しく生成されてしまいます。 @on と ie を @@on と @@ie_ole に変更すれば意図した動作に近づくと思います。

rokino
質問者

補足

InternetExplorer.new(fullscreen = false) と sleep 1 while @@ie.Busy == true この2行をなくすことで意図した動作になりました。 sleepの行をなくさないと `sleep': wrong number of arguments (1 for 0) (ArgumentError) とでてしまいました。

回答No.3

#1のプログラムが動くなら、プログラムを修正すれば大丈夫ですね。 説明があいまいだったせいかうまく伝わらなかったようなので、詳細にOLEコマンドの説明をします。 ie変数は、IEクラスのインスタンスと勘違いしないように、ole_ie変数に変更しています。 ole_ie = WIN32OLE.new("InternetExplorer.Application") # ・・・(1) の部分は、IEの新規ウィンドウを作成するコマンドなので、プログラムを通じて1回だけ実行するようにしましょう。 何度も実行すると、複数のウィンドウが起動します。 ole_ie.visible = true # ・・・(2) の部分は、(2)で作成したウィンドウを画面に表示するためのものです。これを実行せずにプログラムを終了させると、非表示のIEプロセスが残ることになるので、注意しましょう。(タスクマネージャなどで終了可能です。) ole_ie.navigate2(url) # ・・・(3) の部分は、navigate2 メソッドを第2引数を省略して実行すると、(1)で作成したIEウィンドウの既存のタブでブラウズします。 sleep 1 whlle ole_ie.Busy == true # ・・・(4) の部分は、ブラウザが全てを更新するまで1秒間隔で監視して待機します。 ですので#1 の補足のプログラムで、webメソッドを何回も実行すると、(1)が複数回実行され、navigateメソッド、navigate2メソッドどちらを使用しても、新しいウィンドウで表示してしまいます。 #1補足のIEクラスは別のクラスを継承しているとのことなので、IEインスタンスを複数作ることもあるかもしれないので、(1)(2)の部分を分離して、 補足プログラムIEクラスのwebメソッドを下記のようにしてしまいましょう。 def web(url, ole_ie) ole_ie.navigate(url) sleep 1 while ole_ie.Busy == true end その上で、プログラムで1回だけ(1)(2)を実行して、ole_ie変数をwebメソッドに渡すようにすればよいのではないかと思います。 付録として、win32oleを使わない方法も紹介 (1) IEの設定でインターネットオプション→タブの設定→他のプログラムからリンクを開く方法を「現在のタブまたはウィンドウ」に設定 (2) 標準のインターネットブラウザをIEに設定 (3) system("explorer ~~.html")  システムコマンドを使って、IEを呼び出す。 この方法で、IEのタブ設定を変えてしまうとIEの使い勝手が悪くなりますけどね。

rokino
質問者

補足

class IE def initialize(start,fullscreen = false) end def IEnew if @on == nil then @ole_ie = WIN32OLE.new("InternetExplorer.Application") @on = 1 end end def open @ole_ie = InternetExplorer.new(fullscreen = false) @ole_ie.web(~~~.html) end def web(url) self.IEnew @ole_ie.navigate2(url) @ole_ie.Visible = true sleep 1 while @ole_ie.Busy == true return @ole_ie end という感じでやりましたが複数のブラウザが開いてしまいました。 @onはinitializeやその他では定義していない。 また class IE   def initialize(start, fullscreen = false)    ~~    ~~   end   def open     ie = IE.new(fullscreen = false)     ie.web(~~~.html)          end def web(url)     if @on == nil then ie = WIN32OLE.new("InternetExplorer.Application") @on = 1     end     ie.navigate2(url)     ie.visible     sleep 1 while ole_ie.Busy == true     return ie   end end とやっても結果は同じでした WIN32OLE.newを1回だけ実行する部分がうまくできてないようです initializeで@onを定義すると毎回その値が入ってifなどできないし・・・

回答No.2

補足のプログラム拝見しました。 メインのプログラムがどのようにループしているか分からないので、的外れかもしれませんが、 毎回web("~.html") を実行すると、その都度新しいIEウィンドウが作成されますので、最初に開いたものにnavigate2を実行する必要があります。 2回目以降は web(~)の戻したオブジェクトに対して、navigate2を実行してみてください。 #質問と関係ないですしおせっかいかも知れませんが、補足のIEクラスはWIN32OLEクラスを継承したほうが綺麗になると思いますよ。 class IE < WIN32OLE def initialize(start, fullscreen = false) ~~ ~~ super("InternetExplorer.Application") self.visible=true end def web(url) self.navigate2(url) sleep 1 while self.Busy end end 的外れなら、#1で私が書いたサンプルを実行してyahoo!がどう開くか、お手持ちのIE8+cygwinで動作するか、教えてもらえませんか? 新しいウィンドウで開くか、既存のウィンドウ(googleが表示)の新しいタブで開くか、既存のウィンドウの既存のタブで開くか?どれでしょうかね?

rokino
質問者

補足

#1とは一番最初の回答に記載されていたプログラムでしょうか? 実行した結果正常に新しいタブ・ウィンドウを開くことなくgoogleとyahooを開き閉じることが出来ました。 メインプログラムでは<<EOS <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">~~EOS を使ってhtml言語でページを作成し、2回目以降の新しいページは同じファイル名で上書きされて作成されます。 またWin32OLEクラスを継承とありますがIEクラスはすでに他のクラスを継承しているので・・・

回答No.1

win32oleでnavigate2を使えば実現可能ではないでしょうか。 参考URL IEオブジェクトを操作する(VBScript) http://www.happy2-island.com/vbs/cafe02/capter00711.shtml rubyからIEを制御する http://www.tech-notes.dyndns.org/win32ole/ie_ctrl.html リファレンス(英語) http://nerds-central.blogspot.com/2007/02/internet-explorer-ole-com-interface-api.html ↓goolgleを開いて、5秒後にyahooに切り替え、更に5秒後に終了。 require 'win32ole' urls = ["http://www.google.co.jp/","http://www.yahoo.co.jp/"] ie = WIN32OLE.new("InternetExplorer.Application") ie.visible = true urls.each { |url| ie.navigate2(url) sleep 5 } ie.quit

rokino
質問者

補足

現在のプログラムとしては class IE def initialize(start, fullscreen = false) ~~ ~~ end def open ie = IE.new(fullscreen = false) ie.web(~~~.html)        ←ほかのプログラムでhtmlの中身を書き換えてる end def web(url) ie = WIN32OLE.new("InternetExplorer.Application") ie.navigate(url) ie.visible while ie.Busy == true sleep 1 end return ie end end となっています。 kanemoto_sさんの答えのように navigateをnavigate2にしたりと自分なりにいろいろ試しましたがやり方が悪いのかできませんでした IEのVersionは8 initializeで private,new,framemergingをtrueにしています(他はデフォルト?)

関連するQ&A