PHPからCOMを使う

WindowsでIEを制御するためにCOMを使ってみた。
PHPからCOMを使うのは簡単で、「php.ini」からCOMを読み込むように設定すればいいみたいだ。
PHP 5.3.15 / 5.4.5 以前は、デフォルトで読み込まれるらしい。

PHP: インストール手順 – Manual

# php.ini
[COM_DOT_NET]
extension=php_com_dotnet.dll

使いたいコンポーネント名を引数に指定して、COMオブジェクトを生成するだけで使える。
navigate関数で指定ページに移動したあとは、DOMを操作するだけだ。

ページ表示後の待機処理

navigate関数呼び出し後、表示が完了するまで待機するのだけど、いくつか方法がある。
busyプロパティを見て判断する方法が一番簡単なようだ。
しかし、この方法だとDOMが構築される前にループを抜けてしまうため、
DOM要素にアクセスするとエラーになる場合がある。

while ($com_ie->busy) {
com_message_pump(3000);
}

もう一つは、com_event_sink関数で読み込み完了のコールバック関数を指定する方法だ。

class IEEventSinker {
var $completed = false;
var $url = '';
function DocumentComplete(&$dom, $url) {
if ($url == $this->url) {
$this->completed = true;
}
}
function OnQuit() {
$this->completed = false;
}
}
$com_ie = new COM('InternetExplorer.Application', null, CP_UTF8);
$sink = new IEEventSinker();
com_event_sink($com_ie, $sink, 'DWebBrowserEvents2');
while (!$sink->completed) {
com_message_pump(3000);
}

この方法だと読み込み完了のイベントを処理できるので安全らしい。
実際に試したところ、後者の方法でもエラーになることがあった…。
com_message_pump関数を使って、処理待ち状態のメッセージを処理しながらループする。引数の値は、タイムアウトミリ秒だ。0を指定した場合、処理待ちメッセージがなければすぐにFALSEを返す。

ブラウザのビジー状態を判定するための,より良い方法 (WSHでIEを自動操作する際,COMのアプリケーションイベントを利用する) – 主に言語とシステム開発に関して

Yahoo検索を自動化する

Yahoo検索にアクセスしてキーワードを入力後、Submitするものを作ってみた。

<html>sample code.
<?php
class IEEventSinker {
var $completed = false;
var $url = '';
function DocumentComplete(&$dom, $url) {
if ($url == $this->url) {
$this->completed = true;
}
}
function OnQuit() {
$this->completed = false;
}
}
$com_ie = new COM('InternetExplorer.Application', null, CP_UTF8);
$com_ie->visible = true;
$sink = new IEEventSinker();
com_event_sink($com_ie, $sink, 'DWebBrowserEvents2');
$sink->url = 'http://search.yahoo.co.jp/';
$com_ie->navigate($sink->url);
$st = time();
while (!$sink->completed) {
com_message_pump(3000);
if ((time() - $st) >= 5) break;
}
$com_ie->document->forms(0)->p->value = 'php';
$com_ie->document->forms(0)->submit(null);

フォームのClickとSubmitが動かない

最初はWindowsXP上のIE7で試していたのだけど、Windows8上のIE10で上手く動作しない問題が起きた。
フォームの入力は正常にできるのだけど、ClickやSubmitが動作しない。

ググりまくったところ、下記のページを発見し、引数にNULLを指定したところ無事に動作した。
ちなみにIE9以降で起こる問題みたいだ。

Japanese user list of the Ruby programming language ()

参考コード
pontago/php-IECom · GitHub