oExec = WShell.Exec(strCommand)
WShell は Run メソッドと同じく
WshShell オブジェクトです。
返り値が WshScriptExec オブジェクトです。scripts/startpage3.js (ファイルに保存にしてください) ---------------------------------------------------------------- var WShell = WScript.CreateObject("WScript.Shell"); var oExec = WShell.Exec("start http://member.nifty.ne.jp/aya/");Run メソッドのときとどう違うかというと、 これを cscript で実行したときに、新たに DOS プロンプトが立ち上がりません。 すなわち、cscript を実行した DOS プロンプト内で実行されます。 このほうが気分がいいでしょう?
scripts/lha.js (ファイルに保存にしてください) ---------------------------------------------------------------- var WShell = WScript.CreateObject("WScript.Shell"); WShell.Exec("lha32 a js.lzh *.js");でも、標準出力とかは表示されないんですね。
0 : 実行中
1 : 終了
プログラムは基本的に非同期で実行されるようですが、
プログラムの実行終了を判定するには次のようにします。
scripts/calc.js (ファイルに保存にしてください) --------------------------------------------------- var WShell = WScript.CreateObject("WScript.Shell"); var oExec = WShell.Exec("calc"); //実行したcalcが終わるまで待つ while(oExec.Status == 0) WScript.Sleep(100); WScript.Echo("calcが終わったぴょ〜ん!");
scripts/calc2.js (ファイルに保存にしてください) --------------------------------------------------- var WShell = WScript.CreateObject("WScript.Shell"); var oExec = WShell.Exec("calc"); WScript.Sleep(10000); oExec.Terminate();正確にはプロセスに WM_CLOSE メッセージを送るらしい。
Perl を使う人ならよく分かると思うのですが、 例えば ls -lR の結果を取り込むときに次のようにするのと同じようなことです。
open FILES, "ls -lR |";
while(<FILES>) {
...
}
close FILES;
これと同じようなことが WSH でもできるようになりました。
scripts/dir2.js (ファイルに保存にしてください) ---------------------------------------------------------------------------- var WShell = WScript.CreateObject("WScript.Shell"); var oExec = WShell.Exec("command.com /c dir /s"); //NT系はcmd.exeだっけ? var files = oExec.StdOut; var buff; var quit = false; while(true) { while(!files.AtEndOfStream) { buff = files.ReadAll(); //出力された分を読んで files.Write(buff); //そのまま出力する } if(quit) break; quit = (oExec.Status == 1); WScript.Sleep(100); }Perl にくらべて複雑ですね。 これは、MSDNを参考にして書いたのですが、 けっこう微妙です。ちょっとコードが変わると動かなくなったりします。
上の例はあまり意味がないので、もうちょっとましな例を考えてみましょう。 StdOut を使って何が嬉しいのかというと、 テンポラリなファイルを作らなくていいということです。 以前に seek2.js という例を出しましたが、 これをテンポラリなファイルを作らなくてもよいようにします。
scripts/seek3.js (ファイルに保存にしてください) ---------------------------------------------------------------------------- var WShell = WScript.CreateObject("WScript.Shell"); var fs = WScript.CreateObject("Scripting.FileSystemObject"); var objArgs = WScript.Arguments; if(objArgs.length == 0) { WScript.Echo("usage : cscript seek.js ファイル名"); WScript.Quit(); } var oExec = WShell.Exec("command.com /c dir /s " + objArgs(0)); var stream = oExec.StdOut; //とにかく全部読む var status = 0; var str = ""; var quit = false; while(true) { while(!stream.AtEndOfStream) str += stream.ReadAll(); if(quit) break; quit = (oExec.Status == 1); WScript.Sleep(100); } var lines = str.split("\r\n"); //1行ずつの配列にする var arr; while(lines.length > 0) { str = lines.shift(); //前から取り出す arr = str.split(/ /); if(status == 0) { //ヘッダ部分 if(arr[0] == "ディレクトリは") { cfolder = arr[1]; if(cfolder.length == 3) cfolder = cfolder.substring(0, 2); lines.shift(); status = 1; } } else { //リスト部分 if(arr.length == 4) //次のフォルダへ status = 0; else if(str.search(/<DIR>/) == -1) //ファイル WScript.Echo(cfolder + "\\" + str.slice(str.indexOf(":") + 4)); } }読むところ、
while(!stream.AtEndOfStream)
str += stream.ReadAll();
ですが、ここを
while(!stream.AtEndOfStream) {
str = stream.ReadLine();
//処理する
}
とする、すなわち一行ずつ読むとうまくいかないんですね、なぜか。scripts/calc3.js (ファイルに保存にしてください) ---------------------------------------------------------------------------- while(true) { WScript.StdOut.Write("?"); var buff = ""; var c; while(true) { c = WScript.StdIn.Read(1); if(c == "\n") { if(buff.length == 1) WScript.Quit(); WScript.StdOut.WriteLine(eval(buff)); break; } else buff += c; } }単に Enter で返すとプログラムが終了します。
scripts/calc4.js (ファイルに保存にしてください) ---------------------------------------------------------------------------- var qExp = [ "1+2", "Math.sin(Math.PI/6)" ]; var WShell = WScript.CreateObject("WScript.Shell"); var oExec = WShell.Exec("cscript //nologo calc3.js"); var istream = oExec.StdIn; var ostream = oExec.StdOut; var cout = WScript.StdOut; var str; while(!ostream.AtEndOfStream) { str = ostream.Read(1); cout.Write(str); if(str == "?") { if(qExp.length > 0) expression = qExp.shift(); else expression = ""; istream.WriteLine(expression); //式を入力 cout.WriteLine(expression); //エコーする } WScript.Sleep(50); }"?" が出力されると、qExp から1つずつ式を実行しているプログラムに入力します。 qExp が空になったら改行を入力して終わります。
str = ostream.Read(1);のところは、なぜか ReadAll だとうまくいきません。