Java のスクラップブックを HTML + JScript で作る (HTAで子プロセスを操作)
スクラップブックとは,Javaのソースコードの「断片」を,その場ですぐ実行できるというツール。
Eclipseに付属しており,ちょっとしたメソッドの動作確認をしたい時に重宝する。
ちょっと動かすだけじゃない、eclipseスクラップブックページのとても便利な使い方
http://symple.jp/10.html
コンパイル言語なのに,まるでスクリプト言語のように使える。
これの簡易版を HTML+JScript(HTAアプリケーション)で作ってみる。
関連するTipsは
- JScript で,子プロセスを起動して標準出力を得る方法
- JScript で,特定の時間だけスリープする方法
など。
下記ソースコード:
適当な名前.hta で保存。ダブルクリックでGUIが開く。
<html> <head><title>java scrap</title></head> <body bgcolor="#eeeeff"> <center> <h4>javaコード</h4> <textarea cols=100 rows=9 id="txtCode">System.out.println( "Hello,World!" ); //System.out.println( System.getProperties() ); </textarea> <br><br> <input type="button" onClick="exec()" value=" 実行 "> <input type="checkbox" id="cbxDelClass" checked=true> 実行後 .class を消去 <input type="checkbox" id="cbxDelSrc"> 実行後 .java を消去 <br><br> <h4>出力</h4> <textarea cols=100 rows=9 id="txtOutput"></textarea> <br><br> <input type="button" onClick="txtOutput.value=''" value=" クリア "> </center> <script language="JavaScript"> function exec() { // 定数 var ForReading = 1; // 読み込み var ForWriting = 2; // 書き込み(上書き) var ForAppending = 8; // 書き込み(追記) // javaファイル作成 // 新規テキスト var class_name = "TempScrap"; var file_to = class_name + ".java"; var file_class = class_name + ".class"; var fso_w = new ActiveXObject( "Scripting.FileSystemObject" ); if( fso_w.FileExists( file_to ) ) { fso_w.DeleteFile( file_to ); } fso_w.CreateTextFile( file_to ); var txt_w = fso_w.OpenTextFile( file_to, ForWriting ); // ソースコード var strsrc = "class TempScrap {\r\n" + " public static void main ( String args[] ) {\r\n" + txtCode.value + "\r\n" + " }\r\n" + "}" ; txt_w.WriteLine( strsrc ); txt_w.Close(); // コンパイル var excel = new ActiveXObject("Excel.Application"); var cmd_cl = "cmd.exe /c javac " + file_to; var ws = new ActiveXObject( "WScript.Shell" ); // 実行 var ws_cl = ws.Exec( cmd_cl ); while( ws_cl.Status == 0 ) { // ウェイト excel.ExecuteExcel4Macro( "CALL(\"Kernel32\",\"Sleep\",\"JJ\",1000)" ); } var res_cl = ws_cl.StdOut.ReadAll(); // コンパイル成功か調べる if( ! fso_w.FileExists( file_class ) ) { txtOutput.value += "【コンパイル失敗】\n"; return; } // 実行 var cmd_exec = "cmd.exe /c java " + class_name; var ws_exec = ws.Exec( cmd_exec ); while( ws_exec.Status == 0 ) { excel.ExecuteExcel4Macro( "CALL(\"Kernel32\",\"Sleep\",\"JJ\",1000)" ); } var res_exec = ws_exec.StdOut.ReadAll(); // 標準出力を取得 txtOutput.value += res_exec; // 後処理 if( cbxDelClass.checked ) { fso_w.DeleteFile( file_class ); } if( cbxDelSrc.checked ) { fso_w.DeleteFile( file_to ); } return; } // ※古いclassファイルが残ったままだと,コンパイルエラー時には古いclassが実行されます。 </script> </body> </html>
実行画像:
上のボックスにコードを書き,実行ボタンを押下すると,下のボックスに実行結果が出る。
コードの注意点を幾つか:
(1)最初から WScript オブジェクトが無い
HTAなので,ブラウザ上でJScriptを動かしているような状況であり,WSHとは異なる。
var fso_w = WScript.CreateObject( "Scripting.FileSystemObject" );
のかわりに
var fso_w = new ActiveXObject( "Scripting.FileSystemObject" );
とする。
WScript.Echo() でのアラートも不可だから,通常のJavaScriptと同じで alert() を使ってよい。
(2)子プロセスの出力結果を得る際,待つ
WScript.ShellでExecをかければ,外部コマンドを実行できる。
この際,Statusプロパティを監視して,ジョブが実行中かどうかを判定する。
ジョブが終了した時点で完全な標準出力を取得できる。
MS-DOSコマンドの標準出力を取得する
http://officetanaka.net/excel/vba/tip...Status プロパティ (WshScriptExec)
http://msdn.microsoft.com/ja-jp/libra...
- WshRunning ( = 0) ジョブはまだ実行中です。
- WshFinished ( = 1) ジョブの実行が完了しました。
(3)Sleepメソッドが無い
(2)より,ジョブが終了したかどうか待つ必要があるわけだが,(1)の通り WScript が無いので,WScript.Sleep() が使えない。
かわりに,Excelマクロを呼び出すことによってウェイトを実現できる。
excel.ExecuteExcel4Macro( "CALL(\"Kernel32\",\"Sleep\",\"JJ\",1000)" );
これで1000ミリ秒ポーズできる。
setInterval(+mshta)を使ってタイマー処理する方法もある。
HTAを使ってウェイトをかける
http://maglog.jp/pueblo-del-script/in...
基本的なファイル処理については,下記記事中のコードを参照。
バッチで文字列を置換する (JScriptでテキストファイル処理)
http://language-and-engineering.hatenablog.jp/entry/20081017/1224168811
日経平均株価の下落ぶりをMIDIサウンドで味わう (コマンドラインでMIDI生成)
http://language-and-engineering.hatenablog.jp/entry/20081027/1225038111