VBScript 1

Windows 上でのちょっとした定型処理を作ってみる。BAT ファイルでは記述力に限界があるので、VBScript を少し調べてみる。Visual Basic のサブセットで、多少文法が異なるが、BAT に比べれば制御構造などはまし。IE の COM オブジェクトを使うので、悪い予感はあったが、凝ったことをやりだすとバージョンごとの非互換や、UUID やら面倒なことが出てきそう。ZIP ファイルの操作をやるスクリプトが出回ってたので、見てみたが、やっぱり面倒なお約束事が多すぎで、一気にやる気がうせる。あえて、便利なところといえば Drag&Drop を受け付けて引数にして起動できるところぐらいか。エラーメッセージがわかりにくいので、開発の効率は悪い。

あきらめて、メインの処理は python にしてみる。処理系は C# で書かれた IronPython. .Net もいけるらしいが、結局 annotation だらけにしないと DnD とか面倒なので、VBScript から Execute することにしてみる。

python 単体の起動のために .py を ipy.exe に関連付ける。単体で起動できるようになったところで DnD を試すと、受け付けない。エクスプローラで属性をいろいろ見てみるが、DnD に関する設定は見当たらない。実行ファイルの属性なのか?

.py で起動はできても引数がわたってないみたい。少し調べると関連付けの実態は一段階置いて次のレジストリ値で決まるが、ここに設定された値が "C:\Program Files\IronPython 2.6\ipy.exe" "%1" となっている。なんだかんだいって、%1 って BAT の記法じゃないか。これだと引数が多くなるとだめだし、Windows ってワイルドカードの展開はやらないしで、げんなり。

HKEY_CURRENT_USER\Software\Classes\py_auto_file\shell\open\command

結局 VBS 側で ipy のフルパスを入れたものにしてみるが、今度は python のプログラムが実行されていないっぽい。Windows は stdin, out, err の扱いも独特なので、エラーも判別しにくいのだが、Current working directory を表示すると \windows\win32 と出てくる。python 自体は vbs のスクリプトと同じディレクトリにおいておいたので、ファイル名だけで読めるよう、いったん vbs のあるディレクトリに移動する処理が必要。

ここまでやれば、あとは python 側の実装で済むはず。

Windows って一皮剥けば、まだまだ荒削りで、使いにくい... 意味のないおまじないも勘弁してほしい。


Option Explicit
Dim strArgument
Dim a2

a2 = """C:\Program Files\IronPython 2.6\ipy.exe"""
a2 = a2 & " args.py "

'change directory to the script location
ChangeDirToScriptDir

If WScript.Arguments.Count = 0 Then
WScript.Echo "コマンドライン引数が指定されていません。"
Else
For Each strArgument In WScript.Arguments
a2 = a2 & strArgument & " "
Next
End If

Dim objWshShell
Set objWshShell = WScript.CreateObject("WScript.Shell")

Dim objExec
Set objExec = objWshShell.Exec(a2)

WScript.Echo objExec.StdOut.ReadAll

Sub ChangeDirToScriptDir
Dim objFSO
Dim scriptObj
Dim scriptFolder
Dim objWshShell

Set objFSO = WScript.CreateObject("Scripting.FileSystemObject")
Set scriptObj = objFSO.GetFile(Wscript.ScriptFullName)
Set scriptFolder = scriptObj.ParentFolder

Set objWshShell = WScript.CreateObject("WScript.Shell")
objWshShell.CurrentDirectory = scriptFolder
Set objFSO = Nothing
Set scriptObj = Nothing
Set scriptFolder = Nothing
Set objWshShell = Nothing
End Sub