令和になってもなお JScript で VBScript の InputBox を使う

以前、このテーマについて以下のような記事を書いた。

今更だが JScript で VBScript の Inputbox を使う - Qiita
https://qiita.com/itasnasal/items/1747f9bcf6859093b7fe

ここでは wsc (Widows Script Component) を使う、という奇矯な方法に辿り着いた。
しかし。
結局原因は不明なままだが、2回呼び出すと2回目がきちんと動かなかったりとか安定しない。
元々半ば冗談で試した手法で「できるじゃんｗｗｗ」的なところが大きかった。

「少なくとも、全く同じものはWEBではいまのところ見つけられてない。」に尽きる。

そして久しぶりにこの問題をもう一度考えてみた。

「どうにかして JScript から  VBScript を動かして、結果を取得する」

どうすればいいか。


ここで身も蓋もない原点に戻ってきた。

「スクリプトなんだからスクリプト・ファイル作って実行すればいいじゃん。」

というわけで書いたのがこれである。

・InputBox を実行して結果を標準出力に吐くVBScriptファイルを生成する。
・これを WshShell.exec() で実行して、標準出力の内容を取ってくる。

```js
// magic spell for WSH ///////////////////////////////////////////////////////
if(typeof console==="undefined")  console={log: function(s){WScript.Echo(s)}};
if(typeof process==="undefined"){ process={exit:function(e){WScript.Quit(e)}};
var v=process.argv=[];v.push(WScript.FullName);v.push(WScript.ScriptFullName);
var n=WScript.Arguments.Unnamed;for(var i=0;i<n.length;i++)v.push(n.item(i))};
//////////////////////////////////////////////////////////////////////////////

// require('vbFunctions');	// 超原始的に JScript から VBScript の関数を実行する。
initVbsFunction();

var result = vbsMsgBox( 'テストです。', 3+32, 'MagBoxTest' );
console.log( result );

var result = vbsInputBox( 'テストです。', 'InputBoxTest', 'デフォルト値', 3000, 1500 );
console.log( result );

process.exit()


function initVbsFunction() {
//--------------------------------------------------------------------------//

//////////////////////////////////////////////////////////////////////////////
// 超原始的に JScript から VBScript の関数を実行する。
// 現在は以下の２つ。
//
// vbsInputBox( prompt, title, dflt, xpos, ypos, helpfile, context ) 
// vbsMsgBox( prompt, buttons, title, helpfile, context )
// 
// おまけ：とりあえずこれも出しとく。
// vbsFunction( funcName, args ) 

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

// 超原始的に JScript から VBScript の InputBox を実行する。
vbsInputBox = function( prompt, title, dflt, xpos, ypos, helpfile, context ) {
	return vbsFunction( 'InputBox', arguments );
}

// 超原始的に JScript から VBScript の MsgBox を実行する。
vbsMsgBox = function( prompt, buttons, title, helpfile, context ) {
	return vbsFunction( 'MsgBox', arguments );
}

// 超原始的に JScript から VBScript の関数を実行するための共通ルーチン
vbsFunction = function( funcName, args ) {
	
	var vbsPath = genTempNameEx( 'Dummy_', '.vbs' );
	var param = [];
	for (var i = 0; i < args.length; ++i) param[i] = ( '\"'+args[i]+'\"' );

	var vbs = 'WScript.Echo ' + funcName + '( '+ param.join(', ') +  ' )';

	text2file( vbs, vbsPath );
	
	var sce = WScript.FullName.replace(/Wscript/i, "cscript") + " //nologo ";
	var oExec = WshShell.exec(  sce + vbsPath );
	var result = oExec.StdOut.ReadAll().replace(/\r\n$/,"");
	fso.DeleteFile( vbsPath );
	
	return result

}
// %TEMP% 内に一時ファイル名を生成
function genTempNameEx( prifix, postfix ) {	// 一時名前の生成
	prifix  = prifix  || '';
	postfix = postfix || '';
	var tempPath = fso.BuildPath( fso.GetSpecialFolder(2), prifix + fso.GetTempName() + postfix );
	// fso.GetTempName() を使ってみる。
	if( fso.FileExists( tempPath ) || fso.FolderExists( tempPath ) ) throw new Error( '一時ファイル名の生成に失敗しました。' );
	return tempPath;
}

// 指定ファイルを全読みしてテキストで返す。
function file2text( file ) {
	if( ! fso.FileExists( file ) ) return null;
	var f = fso.OpenTextFile( file, 1 );	//  iomode 1:ForReading
	var r = "";
	if( ! f.AtEndOfStream ) r = f.ReadAll();
	f.close();
	return r;
}

// 指定テキストをファイルに保存する。
function text2file( text, file ) {
	var f = fso.CreateTextFile( file, true );
	f.Write(text);
	f.close();
	return;
}

//	module.exports = {};
//--------------------------------------------------------------------------//

}
```

Script Control使って「別の言語のコードを押し込んで使う」んじゃなく
普通に「別の言語のスクリプトファイルを書いて実行する」というシンプルな方法。


最初すごくあほらしいと自分では思ったけれども、１ファイルに収まるし、使っている仕組みも既知のシンプルなもので、内部の動きに wsc のような不明さ謎さもない。


奇矯な方法よりも、いろいろシンプルであることが大事だよなあ。と改めて思いました。