JScript を用いて Lhaplus で自己解凍書庫を作る

久々の投稿となってしまいました。
今回は JScript を用いて Lhaplus を制御し、自己解凍書庫を作成してみます。


Lhaplus をスクリプトで制御するためには、Lhaplus のコマンドラインスイッチを利用しますが、ヘルプを参照したところ、現状コマンドラインスイッチは公開されていないようでした。他サイト様を参照すると、公開されてないものの Lhaplus 自体はコマンドラインで操作が可能とのことです。

開発リソース/Windows/Lhaplusのコマンドライン引数 - isla-plata.org Wiki


実際に試してみたところ、たしかにコマンドラインから操作することが可能でした。ただ、動かしてみた範囲では、書庫の作成が正常に完了する場合も、エラーで終了する場合も、実行ファイルの戻り値として同じ 0 が返却されるため、スクリプト側から Lhaplus の処理の成否を判断するのが難しそうです。

今回はこの部分を何とか外部から判断できないか工夫してみました。できあがったコードが以下です。(zlib/libpngライセンス)

// FileName: createSFX.js

var lpath = "C:\\Program Files\\Lhaplus\\Lhaplus.exe";
var args = WScript.Arguments;

if (args.Length <= 0) {
	var emsg = "Error: 圧縮対象が指定されていません。\n" + 
				"Usage: cscript createSFX.js 圧縮対象の絶対パス";
	WScript.Echo(emsg);
	WScript.Quit(1);
}

try {
	createSFX(lpath, args(0));
} catch(e) {
	var en = e.number & 0xFFFF;
	WScript.Echo("Error: " + e.description + "(" + en + ") ");
	WScript.Quit(en);
}
WScript.Quit(0);

function createSFX(lpath, srcpath) {
	var fso = new ActiveXObject("Scripting.FileSystemObject");
	var sh = new ActiveXObject("WScript.Shell");
	var exec = null;
	var target = "\"" + fso.GetAbsolutePathName(srcpath) + "\"";
	var outdir = "\"" + fso.GetParentFolderName(fso.GetAbsolutePathName(srcpath)) + "\"";
	var logdir = WScript.ScriptFullName.replace(WScript.ScriptName, "");
	var logpath = logdir + "lhaplus.log";
	var cmdline = lpath + " /x /c:zip /log:" + logpath + " /o:" + "" + outdir + " " + target;
	var logfile = null;
	var err = false;
	
	// 前回のログファイルの削除
	try { fso.DeleteFile(logpath, true); } catch (e) {}
	
	try {
		// 自己解凍書庫の作成
		exec = sh.Exec(cmdline);
		
		// Lhaplus の終了待ち
		for (; exec.Status == 0; WScript.Sleep(300)) {
			try {
				// ログ監視
				logfile = fso.OpenTextFile(logpath, 1, false, -2);
				if (logfile.ReadAll().indexOf("エラーまたは警告が発生しています。") > -1) {
					exec.Terminate();
					err = true;
				}
				logfile.Close;
			} catch(e) {
			} finally {
				logfile = null;
			}
		}
		
		if (err || exec.ExitCode != 0) {
			throw new Error(1, "自己解凍書庫の作成でエラーが発生しました。");
		}
	} catch(e) {
		throw e;
	} finally {
		exec = null;
		sh = null;
		fso = null;
	}
	
	return;
}

使い方は、このスクリプトにファイルをドラッグ&ドロップするだけです。ドロップしたファイルと同じフォルダに、入力ファイル名の自己解凍書庫が作成されます。


上記コードの中で、「ログ監視」コメント部分がポイントです。Lhpalus にはログファイルを出力するオプションがあるようで、エラー時はこのログファイルの中に "エラーまたは警告が発生しています。" という文字列が出力されます。これを利用して外部からエラーと判断することができます。


また、Lhaplus の既定の設定では、圧縮処理でエラーが発生した場合に下のようなログウィンドウを表示するようになっています。
f:id:norastep:20141015000830p:plain
このログウィンドウを閉じないと Lhaplus.exe が永遠に終了しないため、エラー時に限って Lhaplus に終了要求を送ります。

ログウィンドウの表示設定は、Lhaplus の詳細設定より下記赤枠の箇所が該当します。
f:id:norastep:20150422205742p:plain

なお、本スクリプトはこの設定以外では動作しません。エラー時のみログウィンドウが表示されることを期待しているためです。