IBM i のエンド・ユーザーに VBS (VBスクリプト)を配布して実行させていると
VBS に変更を生じたときには、すべてのクライアントの再配布しなければ
ならない。
このようなときに IBM i に保存してある VBS スクリプトを実行する方法が
あれば変更があったとしても IBM i の VBS を変更するだけで済む。
要はその昔流行った C/S(クライアント・サーバー)モデルの App の弱点を
補うことができる。
また DOS コマンドを IBM i で動作させることは PC オーガナイザーで
実現することができるのは広く知られているが VBS となると
DOS コマンドのように単純には動作しない。
そこで今回の紹介では 最初に IBM i から VB スクリプトを動作させる
RUNVBS というコマンドを紹介する。
元々、VBスクリプトの実行は弊社製品 Spoolライター Ver5.0 の SNDFAX という
印刷スプールを FAX送信するためのコマンドに利用されている。
SNDFAX は C/400で書かれているため RPG/COBOL の開発者には
理解しにくいと思われるので CLP に書き直している。
実際の SNDFAX は実用上の様々な工夫がソースに配慮されているが
ここでは学習用としてそれらの機能は割愛されている。
0001.00 CMD PROMPT('VBS の実行 ')
0002.00 PARM KWD(VBS) TYPE(*PNAME) LEN(128) CASE(*MIXED) +
0003.00 PROMPT('VB スクリプト ')
VBスクリプトは IFS に保存しておいて上記のパラメータ: VBS で、その IFS のパス名を
入力する。
従ってパラメータ: VBS は TYPE が 128バイトの *PNAMEとして定義されている。
0001.00 PGM PARM(&VBS)
0002.00 /*-------------------------------------------------------------------*/
0003.00 /* RUNVBS : VB スクリプトの実行 */
0004.00 /* */
0005.00 /* 2016/10/25 作成 */
0006.00 /*-------------------------------------------------------------------*/
0007.00 DCL VAR(&VBS) TYPE(*CHAR) LEN(128)
0008.00 DCL VAR(&CMD) TYPE(*CHAR) LEN(132)
0009.00 DCL VAR(&SYSNAME) TYPE(*CHAR) LEN(8)
0010.00 DCL VAR(&MSG) TYPE(*CHAR) LEN(132)
0011.00 DCL VAR(&MSGID) TYPE(*CHAR) LEN(7)
0012.00 DCL VAR(&MSGF) TYPE(*CHAR) LEN(10)
0013.00 DCL VAR(&MSGFLIB) TYPE(*CHAR) LEN(10)
0014.00 DCL VAR(&MSGDTA) TYPE(*CHAR) LEN(132)
0015.00 DCL VAR(&TYPE) TYPE(*CHAR) LEN(1)
0016.00 DCL VAR(&TOPGMQ) TYPE(*CHAR) LEN(10)
0017.00 DCL VAR(&MSGTYPE) TYPE(*CHAR) LEN(10) +
0018.00 VALUE('*ESCAPE ')
0019.00 DCL VAR(&APIERR) TYPE(*CHAR) LEN(116) +
0020.00 VALUE(X'000074') /* 2 進数 */
0021.00 DCL VAR(&NULL4) TYPE(*CHAR) LEN(4) +
0022.00 VALUE(X'00000000')
0023.00 /* VBS のエンコード */
0024.00 DCL VAR(&PCCMD) TYPE(*CHAR) LEN(128)
0025.00 DCL VAR(&STRLEN) TYPE(*DEC) LEN(3 0) VALUE(128)
0026.00 DCL VAR(&STRPOS) TYPE(*DEC) LEN(3 0) VALUE(1)
0027.00 DCL VAR(&PATLEN) TYPE(*DEC) LEN(3 0) VALUE(1)
0028.00 DCL VAR(&RESULT) TYPE(*DEC) LEN(3 0)
0029.00 DCL VAR(&STR) TYPE(*DEC) LEN(3 0)
0030.00 DCL VAR(&NXT) TYPE(*DEC) LEN(3 0)
0031.00 DCL VAR(&LEN) TYPE(*DEC) LEN(3 0)
0032.00 MONMSG MSGID(CPF0000) EXEC(GOTO CMDLBL(ERROR))
0033.00
0034.00 /*( 環境の取得 )*/
0035.00 RTVJOBA TYPE(&TYPE)
0036.00 IF COND(&TYPE *EQ '0') THEN(DO) /* バッチ */
0037.00 CHGVAR VAR(&TOPGMQ) VALUE('*SYSOPR ')
0038.00 ENDDO /* バッチ */
0039.00 ELSE CMD(DO) /* 対話式 */
0040.00 CHGVAR VAR(&TOPGMQ) VALUE('*TOPGMQ ')
0041.00 ENDDO /* 対話式 */
0042.00 RTVNETA SYSNAME(&SYSNAME)
0043.00
0044.00 /*( URL の文字 # をエンコード )*/
0045.00 CHGVAR VAR(&PATLEN) VALUE(1)
0046.00 NXT#: CALL PGM(QCLSCAN) PARM(&VBS &STRLEN &STRPOS '#' +
0047.00 &PATLEN ' ' ' ' ' ' &RESULT)
0048.00 IF COND(&RESULT *NE 0) THEN(DO)
0049.00 CHGVAR VAR(&STR) VALUE(&RESULT - 1)
0050.00 CHGVAR VAR(&NXT) VALUE(&RESULT + 1)
0051.00 CHGVAR VAR(&LEN) VALUE(128 - &RESULT)
0052.00 CHGVAR VAR(&PCCMD) VALUE(%SST(&VBS 1 &STR) +
0053.00 *TCAT '%23' *CAT %SST(&VBS &NXT &LEN))
0054.00 CHGVAR VAR(&VBS) VALUE(&PCCMD)
0055.00 GOTO NXT#
0056.00 ENDDO
0057.00
0058.00 /*( 実行コマンドの作成 )*/
0059.00 CHGVAR VAR(&CMD) VALUE('\\' *CAT &SYSNAME *TCAT +
0060.00 '\ROOT' *CAT &VBS)
0061.00 /*( VBS の実行 )*/
0062.00 STRPCO
0063.00 MONMSG MSGID(IWS4010)
0064.00 CHGVAR VAR(&PCCMD) VALUE(&CMD)
0065.00 STRPCCMD PCCMD(&PCCMD) PAUSE(*YES)
0066.00 RETURN
0067.00
0068.00 APIERR:
0069.00 CHGVAR VAR(&MSGID) VALUE(%SST(&APIERR 9 7))
0070.00 CHGVAR VAR(&MSGDTA) VALUE(%SST(&APIERR 17 100))
0071.00 CHGVAR VAR(&MSGF) VALUE('QCPFMSG ')
0072.00 CHGVAR VAR(&MSGFLIB) VALUE('QSYS ')
0073.00 GOTO SNDMSG
0074.00
0075.00 ERROR: RCVMSG MSGTYPE(*LAST) RMV(*NO) MSG(&MSG) +
0076.00 MSGDTA(&MSGDTA) MSGID(&MSGID) MSGF(&MSGF) +
0077.00 MSGFLIB(&MSGFLIB)
0078.00 SNDMSG: IF COND(&MSGID *EQ ' ') THEN(DO)
0079.00 SNDPGMMSG MSGID(CPF9897) MSGF(QCPFMSG) MSGDTA(&MSG) +
0080.00 TOMSGQ(&TOPGMQ) MSGTYPE(&MSGTYPE)
0081.00 ENDDO
0082.00 ELSE CMD(DO)
0083.00 SNDPGMMSG MSGID(&MSGID) MSGF(&MSGFLIB/&MSGF) +
0084.00 MSGDTA(&MSGDTA) TOMSGQ(&TOPGMQ) +
0085.00 MSGTYPE(&MSGTYPE)
0086.00 ENDDO
0087.00 ENDPGM
RUNVBS VBS('\TEST\HELLO.VBS') のようにして / (バックスラッシュ)ではなく
\ 記号を使ってフォルダーを表現すること。
動作原理は 「\\(システム名)\ROOT(VBスクリプト名)」を
PCオーガナイザーによって起動している。
例えば HELLO.VBS という名前のVBスクリプトを フォルダー /TEST の配下に保存した場合、
\\S652ABCD\ROOT\TEST\HELLO.VBS
という名前のコマンドを実行していることになる。( S652ABCD とはシステム名 )
この原理を理解するには Win エクスプローラの URL 欄に
\\S652ABCD を入力するか、または \\192.168.1.1 ( IBM i のIPアドレス)
を入力して実行すると次のような Basic 認証のダイアログが表示される。
ここで IBM i のユーザー名とパスワードを入力すると Winエクスプローラに
IBM i のパスが表示される。
(一度でもログインしておけば2回目以降の実行ではログインが再び要求されることはない。)
その中で ROOT という名前のフォルダーを展開すると IBM i の IFS の内容が
展開される。
( ROOT=根っこというのはIFSツリー構造の最上位を意味する)
STRPCCMD PCCMD(&PCCMD) PAUSE(*YES) の PAUSE(*YES) は
デバッグが終わって正常に実行されることを確認したのであれば
PAUSE(*NO) にすることが望ましいだろう。
VBスクリプトの実行はほんの簡単な入口であるが、これは IBM i のオープン化の
発端を示している。もしこの IFS に VisualBASIC や VC++, あるいは Java で
書かれた .exe や .class を配置すれば原理的に IBM i に存在している VB や Java を
起動することができることを理解して頂けるのではないかと思う。
ただし IBM i の DB2/400データ・ベースは Visual BASIC や Java からは簡単には
アクセスすることはできない。
もしデータ・ベースも含めてのシームレスな結合ができれば
IBM i を VisualBASIC で普通に開発することができるようになるのかもしれない。
近年、RPG の開発者が減っている傾向に対しては 開発も含めて IBM i のオープン化が
必要になってくる。