2010-03-31

SleipnirでPerlを使う。

下準備

ActivePerl をインストール。

厳密には Perl じゃなくて PerlScript を使います。
ドキュメントは %perl%/html/Windows/WindowsScriptHost.html


Sleipnirスクリプト(WSH) で PerlScript を使う

%Sleipnir%/scripts/ に入れて使う方法。

標準では .pls に関連付けられているので
作ったものを hoge.pls など適当に名前をつけて保存。

%Sleipnir%/scripts/ に入れる。
メニューバー → スクリプト から実行。


.pls がプレイリストとバッティングしてる場合は
どう関連付けを変更すればいいのかわかりませんが

のような書き方で hoge.wsf として保存すれば実行できます。


UserActionスクリプト で PerlScript を使う

%Sleipnir%/plugins/scripts/ に入れて使う方法。

%Sleipnir%/resources/languages/default/english/ScriptEngine.ini
に追記することで対応言語を増やせるので
[StringTable]
js=JScript
vbs=VBScript
となっているのを
[StringTable]
js=JScript
vbs=VBScript
pl=PerlScript
と変更。

あとは作ったものを hoge.pl など適当に名前をつけて保存。
%Sleipnir%/plugins/scripts/
に入れればActionとして使えます。

もちろん Perl のモジュールも使い放題。
公式?の Sleipnir.pm というのもありますよ。

- 参考記事 -
UserAction Extension でオレオレスクリプトのススメ (1) (フェンリル | デベロッパーズブログ)
UserAction Extension でオレオレスクリプトのススメ (2) (フェンリル | デベロッパーズブログ)
UserAction Extension でオレオレスクリプトのススメ (3) (フェンリル | デベロッパーズブログ)
UserAction Extension でオレオレスクリプトのススメ (4) - そして伝説へ - (フェンリル | デベロッパーズブログ)
その後の「UserAction Extension でオレオレスクリプト」 (フェンリル | デベロッパーズブログ)

日本語使うとエラー出たりする

PerlScript で日本語が含まれると読み込まれるbyte数が短くなる。

PerlScript - miau's blog?
ActivePerlのPerlScriptで日本語
Bug 40776 – 2-byte character problem with PerlScript

これはうちの環境、winXP SP3、Sleipnir2.9.3、ActivePerl v5.10.1でも発生。
use strict;
use warnings;
use Win32::OLE;

my $pnir     = Win32::OLE->CreateObject("Sleipnir.API");
my $id       = $pnir->GetDocumentID($pnir->ActiveIndex);
my $window   = $pnir->GetWindowObject($id);
my $document = $pnir->GetDocumentObject($id);

if(!$document) {
 $pnir->Beep();
 $pnir->MessageBox("エラー:Documentオブジェクトが作成できませんでした");
} else {
 $pnir->Beep();
 $pnir->MessageBox("寿限無寿限無五劫の擦り切れ海砂利水魚の水行末雲来末風来末食う寝る処に住む処やぶら小路の藪柑子パイポパイポパイポのシューリンガンシューリンガンのグーリンダイグーリンダイのポンポコピーのポンポコナーの長久命の長助");
}

__END__ 
原因は内部処理で文字数とbyte数がごっちゃになってるせいらしい。
UTF8で書いても回避できません。

ずいぶんとほったらかしのバグですが、いまだに "Status: UNCONFIRMED" ってなんで?


解決するには
 1. 日本語を使わない。
 2. ファイル全体の文字数 > スクリプト部分のバイト数 になるようにスペース等を入れて調節する。
 3. require や use で動的・静的コンパイルする。
のどれかのようです。


では、動的・静的コンパイルを試してみましょう。
Sleipnir のインストール先は C:/sleipnir293/ とします。

Sleipnirスクリプト(WSH)
C:/sleipnir293/
 └ scripts/
  ├ JugemuPLS.pls
  ├ JugemuPM.pm
  ├ call_JugemuPLS.pls
  └ call_JugemuPM.pls

# JugemuPL.pl, JugemuPLS.pls, JugemuPM.pm
use strict;
use warnings;
use Win32::OLE;

my $pnir     = Win32::OLE->CreateObject("Sleipnir.API");
my $id       = $pnir->GetDocumentID($pnir->ActiveIndex);
my $window   = $pnir->GetWindowObject($id);
my $document = $pnir->GetDocumentObject($id);

if(!$document) {
 $pnir->Beep();
 $pnir->MessageBox("エラー:Documentオブジェクトが作成できませんでした");
} else {
 $pnir->Beep();
 $pnir->MessageBox('寿限無寿限無五劫の擦り切れ海砂利水魚の水行末雲来末風来末食う寝る処に住む処やぶら小路の藪柑子パイポパイポパイポのシューリンガンシューリンガンのグーリンダイグーリンダイのポンポコピーのポンポコナーの長久命の長助');
}

1;
__END__
# call_JugemuPLS.pls
use lib qw(C:/sleipnir293/scripts);
require 'JugemuPLS.pls';
# call_JugemuPM.pls
use lib qw(C:/sleipnir293/scripts);
use JugemuPM;

call_JugemuPLS.pls, call_JugemuPM.pm をそれぞれ実行。
Shift-JIS以外だと文字化けしますが、エラーは出ません。


UserActionスクリプト
C:/sleipnir293/
 └ plugins/
  └ scripts/
   ├ JugemuPL.pl
   ├ JugemuPM.pm
   ├ call_JugemuPL.pl
   └ call_JugemuPM.pl

# call_JugemuPL.pl
use lib qw(C:/sleipnir293/plugins/scripts);
require 'JugemuPL.pl';
# call_JugemuPM.pl
use lib qw(C:/sleipnir293/plugins/scripts);
use JugemuPM;

call_JugemuPL.pl, call_JugemuPM.pl をそれぞれ実行。
これもエラーは出ません。


もう少し何とかする
実行ファイル と 呼び出すファイル の2つが必要とはいえ
日本語がエラーなしで使えるのはありがたい。

そこでもう少し環境を詰めてみる。

.pm はモジュールなのでモジュール以外には使わない。

呼び出すファイルが
 Sleipnirスクリプト(WSH) は .pls
 UserActionスクリプト は .pl
というのは管理が煩雑になるので .pls に統一する。

Sleipnir.pm もあることだし %perl%/site/lib/Sleipnir/ 以下にスクリプトを放り込んでおけば
Sleipnirスクリプト(WSH) でも UserActionスクリプト でも
use lib しなくていいので便利かなと。

C:/perl/
 └ site/
  └ lib/
   ├ Sleipnir/
   │ ├ UAS_hoge.pls
   │ └ WSH_hoge.pls
   └ Sleipnir.pm
実行環境の違いも考慮するならこうした方がいいのかな。
C:/perl/
 └ site/
  └ lib/
   ├ Sleipnir/
   │ ├ UAS/
   │ │ └ UAS_hoge.pls
   │ └ WSH/
   │  └ WSH_hoge.pls
   └ Sleipnir.pm
C:/sleipnir293/
 ├ scripts/
 │ └ call_WSH_hoge.pls
 └ plugins/
  └ scripts/
   └ call_UAS_hoge.pls
ディレクトリで分けるかどうかはお好みで。


ということで変更点は3つ。

1. ScriptEngine.ini を編集。
C:/sleipnir293/resources/languages/default/english/ScriptEngine.ini

[StringTable]
js=JScript
vbs=VBScript
pl=PerlScript
pls=PerlScript
に変更して UserActionスクリプト で *.pls を実行できるように。


2. 実行ファイルと Sleipnir.pm を設置。
C:/perl/
 └ site/
  └ lib/
   ├ Sleipnir/
   │ ├ UAS_hoge.pls
   │ └ WSH_hoge.pls
   └ Sleipnir.pm
# 実行ファイルのテンプレはこんな感じで。
# 日本語が使えます。

# 一応 package 使った方がいいかも。
package Sleipnir::hoge;

use strict;
use warnings;
use Sleipnir;

my $pnir     = Sleipnir->new;
my $id       = $pnir->id;
my $window   = $pnir->window($id);
my $document = $pnir->document($id);

if(!$document) {
 $pnir->Beep();
 $pnir->MessageBox("エラー:Documentオブジェクトが作成できませんでした");
} else {
 # code
}

# この 1 は必須です。
1;
__END__

3. 呼び出すファイル(*.pls)を設置して実行。
C:/sleipnir293/
 ├ scripts/
 │ └ call_WSH_hoge.pls
 └ plugins/
  └ scripts/
   └ call_UAS_hoge.pls
require 'Sleipnir/WSH_hoge.pls';
require 'Sleipnir/UAS_hoge.pls';

__END__
# 呼び出すファイルのテンプレはこんな感じで。
# 日本語でコメントを書く場合は __END__ 以下に書けます。


実際に動かしてみる
C:/perl/
 └ site/
  └ lib/
   ├ Sleipnir/
   │ └ Jugemu.pls
   └ Sleipnir.pm
C:/sleipnir293/
 ├ scripts/
 │ └ call_Jugemu.pls
 └ plugins/
  └ scripts/
   └ call_Jugemu.pls
# Jugemu.pls
package Sleipnir::Jugemu;

use strict;
use warnings;
use Sleipnir;

my $pnir     = Sleipnir->new;
my $id       = $pnir->id;
my $window   = $pnir->window($id);
my $document = $pnir->document($id);

if(!$document) {
 $pnir->Beep();
 $pnir->MessageBox("エラー:Documentオブジェクトが作成できませんでした");
} else {
 $pnir->Beep();
 $pnir->MessageBox('寿限無寿限無五劫の擦り切れ海砂利水魚の水行末雲来末風来末食う寝る処に住む処やぶら小路の藪柑子パイポパイポパイポのシューリンガンシューリンガンのグーリンダイグーリンダイのポンポコピーのポンポコナーの長久命の長助');
}

1;
__END__
# call_Jugemu.pls
require 'Sleipnir/Jugemu.pls';

__END__
これでもShift-JIS以外は文字化けするので
文字コードが問題になるのなら
UTF8で書いてShift-JISで出力すればOK。
# JugemuUTF8.pls
package Sleipnir::JugemuUTF8;

use utf8;
use strict;
use warnings;
use Encode qw/encode/;

use Sleipnir;

my $pnir     = Sleipnir->new;
my $id       = $pnir->id;
my $window   = $pnir->window($id);
my $document = $pnir->document($id);

if(!$document) {
 my $txt = 'エラー:Documentオブジェクトが作成できませんでした';
 $txt = encode('Shift_JIS', $txt);

 $pnir->Beep();
 $pnir->MessageBox($txt);
} else {
 my $txt = '寿限無寿限無五劫の擦り切れ海砂利水魚の水行末雲来末風来末食う寝る処に住む処やぶら小路の藪柑子パイポパイポパイポのシューリンガンシューリンガンのグーリンダイグーリンダイのポンポコピーのポンポコナーの長久命の長助';

 $txt = encode('Shift_JIS', $txt);

 main::MsgBox($txt);

 $window->alert($txt);

 $pnir->Beep();
 $pnir->MessageBox($txt);
}

1;
__END__

こんな感じでいかがでしょうか?
早くバグ修正してくれないかなー。


- 関連記事 -
Aragger: Sleipnirのスクリプトがわかりにくいので整理してみる。

0 コメント:

コメントを投稿