GUIのダイアログを使う場合の肝について
バッチファイルはこの例では「usrOpe.bat」としています。
エンドユーザーに使ってもらう場合はデスクトップにショートカットを作成するなどし、プロパティで[実行時の大きさ]を[最小化]にしておくとよいでしょう。
ディレクトリの構成については、すべてのファイルが同じ階層にあれば基本的にどこに置いても構いません。ただし、Windows 2000の場合は、パスが半角英数のみである必要があります(後述します)。
では、各ステップの肝となる部分を説明して行きます。添付ファイルを参照してください。
まず、バッチファイルの頭に書いてある、
set usrOpeHome=%~d0%~p0
これは何を意味しているかと言うと、このバッチファイルの存在する場所を取得しています。「%d0」はバッチファイルのドライブレター、「%p0」はファイルのフルパスで、半角チルダは「引用符があれば外す」という意味です。
バッチファイルを直接ダブルクリックで実行(または、ショートカットを作成して実行)する場合、小物として使うVBScriptとコマンドライン・アプリは同じパス上にあるので、このHomeディレクトリのパスが切ってなくても問題はありません。
しかし、次のように実行したらどうでしょう?
C:\> C:\xxxxx\test\usrOpe.bat
この場合は、実行パスは「C:\」なので、「usrOpe.bat」から呼ばれる小物達が「パスの通った場所」にいない限り、実行時にエラーになるはずです。「タスクでバッチ実行」や「cronでシェルスクリプト実行」する時にも同様の問題が発生します。
つまり、ここでは、ファイル名に「%~d0%~p0」を付加することで小物達のパスを通している、というわけです。
次に、
set msgboxMsg2=vbYesNo
変数msgboxMsg2にセットしているVB定数については、「msgbox.vbs」の中で、以下の代表的なものについてのみ対応しています。
- vbOKOnly
- vbOKCancel
- vbYesNoCancel
- vbYesNo
- vbCritical
- vbQuestion
- vbExclamation
- vbInformation
そして次がこのバッチで最も肝である部分。小物達の実行結果を、どのように環境変数に格納するか、です。
この小物達は、すべて「結果を標準出力に出力する」という点で共通しています。バッチからこれらを実行した時の結果は、以下の方法で変数に格納できます。
for /f "usebackq tokens=*" %%i in (`call <コマンド名>`)do @set <変数名>=%%i
シェルスクリプトを書く人であれば、「バッククォートで括ったコマンドの結果を変数に格納」する方法をよく使われると思います。同様に Windowsのバッチでもバッククォートを使って(usebackq)、結果を変数に格納できるわけです(コマンドがかなり長くなりますが)。
先ほど、Windows 2000の場合はファイルの置き場所を半角英数のみのパスにする必要があると、述べました。理由は、Windows2000の場合、日本語などのダブルバイトを含んだパスでは上記コマンドがエラーになってしまうからです。これはOS上の制限です。Windows XP以降であれば、ダブルバイトのパスでもOKです。
小物を実行した後は、変数に結果が格納されています。これを処理の判断材料に使うわけです。
for /f "usebackq tokens=*" %%i in (`call cscript //nologo"%usrOpeHome%msgbox.vbs"`) do @set usrOpeResult=%%i if "%usrOpeResult%" == "7" ( set usrOpeStatus=CANCEL goto endofthis ) if not "%usrOpeResult%" == "6" ( set usrOpeStatus=ERROR goto endofthis )
for /f "usebackq tokens=*" %%i in (`call cscript //nologo"%usrOpeHome%inputbox.vbs"`) do @set usrOpeResult=%%i if "%usrOpeResult%" == "" ( set usrOpeStatus=NO_INPUT goto endofthis )
for /f "usebackq tokens=*" %%i in (`call "%usrOpeHome%commdlg"`)do @set usrOpeResult=%%i if "%usrOpeResult%" == "" ( set usrOpeStatus=NO_FILE goto endofthis )
for /f "usebackq tokens=*" %%i in (`call "%usrOpeHome%commdlgd"`)do @set usrOpeResult=%%i if "%usrOpeResult%" == "" ( set usrOpeStatus=NO_DIR goto endofthis )
このようにして小物達がすべて実行されると、継続する処理に必要な情報は揃ったことになるので、以降の処理は業務的なバッチを記述してください。
バッチの終わりに終了メッセージを表示します。ここでは標準出力の結果はもう不要です。nulデバイスにリダイレクトして画面上に出さないようにしておきましょう。
call cscript //nologo "%usrOpeHome%msgbox.vbs" >nul 2>&1
おわりに
「usebackqを使ってコマンド結果を変数へ格納する」というこの方法は、他のさまざまな既存のツールと組み合わせ可能です。
今さらDOSコマンドでバッチを書くのは苦痛だ、という人が無理にこの方法を取る必要はありません。しかし、バッチを書くのが苦痛ではない人や、普段シェルスクリプトを書いていて、DOSのバッチに「IF分岐」「FORループ」「コマンドのバッククォート括り」などがあることを知らなかったという人は、「モノは試し」程度の気持ちでよいので活用してみてください。
参考資料
- 『コモンダイアログの表示』 護法童子 著
- Win32工作室 『フォルダの参照ダイアログを表示するには』 T-Matsuo 著

do @set <変数名>=%%i