今更だが JScript で VBScript の Inputbox を使う

  • 2
    Like
  • 5
    Comment

なんとWSH/JscriptにはInputBox/MsgBoxがない。
WSH/VBScriptにはあるのだが。

JscriptでInputBoxを使うには次のようなやり方がある。

(1) Windows スクリプト ファイル (.wsf) を使用して、VBScript の InputBox() を使う。

(2) Excel VBA の InputBox() を使う。

(3) Windows Script Control を利用して、VBScript の InputBox() を使う。

【参考】
Script/TipsJScript - 備忘録
http://apis.jpn.ph/fswiki/wiki.cgi?page=Script%2FTipsJScript

一番普通なのは(1)だ。

私は「身近な他人にも使ってもらうスクリプト」を書くことがあるので、
・いろんなWinodws(W7~W10, 32/64bit)で動く。
・特別の前提、インストールや設定作業、前準備等なしに動かせる。
・なるべく構成物をシンプルに。できれば1ファイル。
・やむなく複数ファイルにする場合も、一緒に置きさえすればどこに置いても動く。
といったあたりを条件にしてる。

これらを踏まえると、やはり(1)が一番いいことになる。
(2)はExcelが必要だし、こんな程度の事にExcelのインスタンス起こすのもちょっとなんだか。
(3)は妙案だが、Windows Script Controlは64ビット非対応。

で、(1)なんだが、実は私は.wsfがあんまり好きじゃない。
.wsfは「実行ユニットを構成するためのコンテナ」と捉えてるので、できれば中に直接コード書きたくない。
「Jscriptは.jsとして書きたい」んだわ。そうなると構成ファイル数が増える。

(2)については、WordやExcelのおたすけスクリプトを書くこともあるので、そういう時はこれでもいいかな、とは一瞬思った。
マクロにしない理由は、マクロは「中に入れないといけない」しいろいろ面倒くさい。
それにVBA書かないといけない。
もうVBナントカは嫌だ。連想配列が言語仕様になくてオブジェクト作らないといけないとか。
WSHからWord/Excelのオブジェクト起こせば、外からJscriptで同じことが出来る。
だから私はそうしてる。

ところが驚いたことに、ExcelのApplicationオブジェクトはInputBoxメソッド持っているが、Wordは持ってないのだ。
なんだよそれ。ふざけんな。

てなわけで、しばらくは拾ってきたコード使って(3)でやってました。
しかし64ビット非対応だもんで、最近になってちょっと困ったことに。
「64ビットだったら自身を32ビットで再起動する」コードを頭に足してしのいでました。

しかし。
なんだかいろいろ美しくない。
32ビット再起動は美しくないし、さらにScript Control使って「別の言語のコードを押し込んで使う」てのも美しくない。
まあそれの正しい形で一番美しいのは(1)なんだが、モジュール構造を別にXMLで記述しないといけない、というのがなんだが気に入らない。
全てJscriptで。出来ればナントカ.js風に「var InputBox = rquire("vbsInputBox"); 」書けるようにしたいじゃないか。
(ちなみに今のところナントカ.jsを使ってないのはCOMオブジェクトを扱えるようにしようとするといろいろ面倒だから。)

そこへ向けての布石として、もう少し疎にVBScript の InputBox()を使う方法はないもんだろうか。
と、いろいろな方法を探ってみた。
(.net frameworkのVisualBasic 名前空間のオブジェクトはWSHからは扱えなさそうだし。)

そして辿り着いたのがこれだ。
少なくとも、全く同じものはWEBではいまのところ見つけられてない。

vbsWrapper2.wsc
<!-- vbsの InputBox とか MsgBox とかをラップするWSC -->
<component>
<public>
<method name="InputBox" />
<method name="MsgBox" />
<property name="method_InputBox" />
<property name="method_MsgBox" />
</public>
<script language="JScript">
// InputBox
function InputBox( prompt_, title_, default_ ) {
  return vbsInputBox( prompt_, title_, default_ );
}
// MsgBox
function MsgBox( prompt_, Buttons_, title_ ) {
  return vbsMsgBox( prompt_, Buttons_, title_ );
}
// method Entry
var method_InputBox = InputBox;
var method_MsgBox = MsgBox;
</script>
<script language="VBScript">
' InputBox
function vbsInputBox( prompt, title, default )
  vbsInputBox = InputBox( prompt, title, default )
end function
' MsgBox
function vbsMsgBox( prompt, Buttons, title )
  vbsMsgBox = MsgBox( prompt, Buttons, title )
end function
</script>
</component>

利用側の例はこちら。
ふたつを同じ場所に置いておく。

etude_wsc2.js
var WshShell = new ActiveXObject("WScript.Shell");
var fso = new ActiveXObject("Scripting.FileSystemObject");

var cwd = fso.GetParentFolderName(WScript.ScriptFullName);
var wscPath = fso.BuildPath( cwd, "vbsWrapper2.wsc" );

// ①オブジェクトのメソッド
var vbs = GetObject("script:"+wscPath );
var data = vbs.InputBox("何か入力してね。", "WSCサンプル1", "初期値");

vbs.MsgBox( data + "ですね。", 64+1, "WSCサンプル1" );
// 64:vbInformation 情報メッセージ アイコンを表示します。
// 1:vbOKCancel     [OK] ボタンと [キャンセル] ボタンを表示します。

// ②globalにimport
var InputBox = vbs.method_InputBox;
var MsgBox = vbs.method_MsgBox;

var data = InputBox("何か入力してよ。", "WSCサンプル2", "ほげほげ");
MsgBox( data + " かよ。", 64+1, "WSCサンプル2" );

まあ実際は.wsfと同じことだし、大差ないかもしれない。
.wsfなら1ファイルに出来るがこれは2ファイルだ。

だがしかし。このアプローチはナントカ.js風につながっていく余地がある。

これはこれでいびつかもしれない。
でも自分としては満足だ。
自分にとっては上記の(1)~(3)のいずれよりもマシだ。2ファイルになるけど。
でも.wsfと異なり、自身に手を加えることなく再利用可能だ。
なにより「自分で思い付いた」感の自己満足が心地よい(笑)。

次のステップは、これをナントカ.js風のモジュールに発展させることだ。

そのためには require が必要だが、実は「なんちゃってrequire」はもうすでに動いている。
次回はこいつを紹介したい。

ではまた。