Windows Script Host (WSH)


 
CScript ふたりのホスト
 

 Windows の GUI 環境からバッチ処理をしたい。そんな目的で試していると混乱することがあった。実行方法に二通りあり、どちらかで使えないメソッドやプロパテイがあるのに気付くのは、混乱した後からだ。 僕だけじゃないみたい。googleで解決のヒントを検索していると、同じようなQ&Aをみかけた。
 Windows98から導入されたWindows Script Hostの仕組みはC:\WINDOWSにあるwscript.exeです。もう一つC:\WINDOWS\COMMANDにcscript.exeがあり、これはコマンドライン用です。ホストが二人いた訳です。

 どちらのホストも、スクリプトの実行時、C:\WINDOWS\SYSTEMのwshom.ocx、vbScript.dll jscript.dllを利用してスクリプトを実行します。玄関先にポーターが二人いたということでしょうか。

1.  スクリプトをダブルクリック

 Windows の GUI 環境からスクリプトを実行。これには、エクスプローラ内またはデスクトップ上でスクリプトをダブルクリックする。

 この場合、インストールの初期設定はwscript.exeがホストです。

2.   スクリプトを右クリック   

 Windows エクスプローラ内でスクリプトを右クリックします。 [開く] をクリックするとwscript で実行します。cscript で実行するには [MS-DOS プロンプトで開く] (Windows 9x の場合) をクリックし、cscriptとタイプ入力して使います。

3. DOSプロンプトのコマンド ライン

 DOSプロンプトのコマンド ラインに「cscript」または「wscript」と入力し、続けてスクリプトの名前を入力します。

 この場合、ホストが選べます。


 

既定のホスト
 

 インストール後の初期状態では、wscript が既定のホストとして設定されています。既定のホストを cscript に変更するには、コマンド ラインに次のように入力します。
cscript //h:cscript    これ以後DOS窓でcscriptにより実行される。

また、cscript から wscript に切り替えるには、次のように入力します。
cscript //h:wscript

上の1.の場合、既定のホストの設定によって結果が違います。注意しましょう。


 

拡張子とホスト
 

 JScript(JavaScript)でコーデングすると拡張子はJSです。VBScriptですとVBS。XML形式にまとめるとWSFです。

 関連付けされていない拡張子を持つスクリプト ファイルをダブルクリックした場合は、[ファイルを開くアプリケーションの選択] ダイアログ ボックスが表示されます。このダイアログ ボックスで wscript を選択し、[このファイルを開くときは、いつもこのアプリケーションを使う] チェック ボックスをオンにすると、wscriptが既定のアプリケーションとして登録されます。

 拡張子ごとに、既定のホストに違いがあるかもしれません。注意しましょう。
 .wsf ファイルを使うと、スクリプトごとにオプションを設定することができます。この形式に慣れるのがいいかもしれません。


 

ホストと標準出力
 

 "バッチ" と "インタラクティブ" の 2 つのモードがあります。

インタラクティブ モード (既定) では、スクリプトとユーザーとの対話機能が提供され、Windows Script Host に対する入出力が有効になります。スクリプトは、情報をダイアログ ボックスに対してエコーしたり、ユーザーの入力を待機することができます。

 バッチ モードでは、このようなユーザーとの対話はサポートされません。WSH に対する入出力は無効になります。
 また、Windows Script Host コマンド ラインのスイッチ //I (インタラクティブ) と //B (バッチ) を使って、スクリプトのモードを設定することができます。

"インタラクティブ"はwscript.exe、"バッチ"はcscript.exeと思い込むのも、早合点のようです。

まとめます。
wscript.exeはGUI環境からスクリプトを実行する。DOS窓は開かない。
DOS窓からの実行もできる。標準出力はメッセージボックス

cscript.exeはDOSプロンプト用。標準出力は画面(コンソール)。
関連付けによりGUI環境からダブルクリックで実行させられる。
ArgumentsオブジェクトとStdOut StdIn StdErrが有効になる。

両者"バッチ" と "インタラクティブ" の 2 つのモードがある。


 
StdOut  StdIn   StdErr
 

 入力、出力、エラー出力の既定デバイスを標準入力StdIn、標準出力StdOut、標準エラー出力stdErrと呼ぶ。 具体的には、キーボードを標準入力、モニター画面を標準出力と考えていいのだろう。
 cscript.exeを既定ホストにして、これを利用して見よう。

WScript.StdOut.WriteLine("***Expression -> String*** (Quit= q )"); while(true) { WScript.StdOut.Write("Input: "); var Input = WScript.StdIn.ReadLine(); if(Input.toLowerCase() == "q") break; var Result; try { Result = eval(Input); WScript.StdOut.WriteLine("Result: " +Result.toString()); } catch(e) { WScript.StdErr.WriteLine("--------bad expression"); } } WScript.StdOut.WriteLine("--Quit--"); WScript.Quit();

 WScriptオブジェクトは宣言なしで使える。数式(expression)の検算ツールを上のようにJSファイルで用意しておく。ダブルクリックでDOS窓が開き、利用できる。便利な使い捨てプログラム。
 WScriptはjavaScript互換のJScriptで解釈される。豊富なステートメントを使えるのがありがたい。


 WScriptの子供オブジェクトにShellオブジェクトがある。このShellオブジェクトのEXECメソッドを実行すると、StdOut、StdIn、stdErrにアクセスできる。ただし、cscript.exeを使う場合と限定されている。また、インタラクティブモードでないと意味がない。

var WshShell = WScript.CreateObject("WScript.Shell"); var oExec = WshShell.Exec("%comspec% /c dir /p"); var out=""; var outdata=""; var errdata=""; while (oExec.Status == 0) { if (!oExec.StdOut.AtEndOfStream) { outdata = oExec.StdOut.ReadAll(); if (outdata.indexOf("続ける") != -1){WScript.StdIn.Write("~");} out+=outdata; } if (!oExec.StdErr.AtEndOfStream) { errdata ="STDERR: " + oExec.StdErr.ReadAll(); WScript.Echo(outdata); out+=errdata; } WScript.Sleep(100); } WScript.Echo(out); WScript.Sleep(10000);

 Shellお決まりのDIRを実行させてみる。

 cscript.exeを使うと、画面には何も表示しない。StdOut  StdIn  StdErrの制御を書いておかなければならない。ただ、WshShell.Exec("%comspec% /c dir /p")のStdOut  StdIn  StdErrと、WScriptのそれがあることを念頭に入れておく。 WScript.WshShell.Exec.StdOutをモニターして、WScript.StdOutに出力するといった感じだ。WScript.StdOut.WriteLine()はWScript.Echo()ということ。

 DIRというプロセスのStdOut  StdErrは読み取り専用。プロセスが終了すると公開される。Exec("%comspec% /c dir")は正常終了するが、Exec("%comspec% /c dir /p")は、上のコードでは、無限ループを抜け出さない。
 つまり、”続けるには、何かキーを押してください”という、プロセス途中の標準出力は拾えないということのようだ。スクロールアップできないDOS画面のために、割り込みで表示された”続けるには、何かキーを押してください”を、インタラクトブに拾ってStdInにEnterを出力しようとする上のコードは無力だった。プロセスは中断されているので、StdOutには何もデータが掃き出されない。無限ループを抜け出さないと推定した。マニュアルの「WshScriptExec オブジェクトは WshShell オブジェクトの Exec メソッドによって返されます。これは、スクリプトまたはプログラムの実行終了後または実行開始前のいずれかに行われます。」とあることの意味は、こういう事のようだ。Windows98,WSH5.6での事情だが、一つの事例として書き留めておきます。


2004.7.13
by Kon