wsh(.wsf、Windows Script File)のスクリプトを育てる(1)

wshの書き方と起動方法

webで調べると*.vbs*.js*.wsfの三種類が挙がってくるが、 スクリプトをダブルクリックで起動したときにWScript.echoを使ったらダイアログに出力されます。

【vbsの例】 ... sample_wsh1.vbsで保存&実行してみましょう

WScript.Echo "hello!!"

【jsの例】 ... sample_wsh1.jsで保存&実行してみましょう

WScript.Echo("hello!!");

これはこれでとっつきやすくて良いのですが、 少しづつ込み入った事をやろうとしてデバッグ用の出力を追加すると途端に面倒なことになってきます。
ここで対策として思いつくのはバッチファイルでcscriptを使う方法です。

【batの例】 ... sample_wsh1.batで保存&実行してみましょう

cscript  sample_wsh1.vbs
pause

または

cscript  sample_wsh1.js
pause

これもこれでとっつきやすくて良いのですが、 ファイルが2個になって面倒な感じがしませんか? しますよね?

ここでお勧めするのは拡張子がwsfのスクリプトです。 しかしひとまずはhello!!を表示させるスクリプトをwsfの書き方にしてみましょう。

【wsf(vbs)の例】 ... sample_wsh2.wsfで保存&実行してみましょう

<job>
    <script type="text/javascript">
        WScript.echo("hello!!");
    </script>
</job>

【wsf(js)の例】 ... sample_wsh3.wsfで保存&実行してみましょう

<job>
    <script language="vbscript">
        WScript.Echo "hello!!"
    </script>
</job>

スクリプトの種類について、 vbsはlanguage="vbscript"しか受け付けない様子です。 また、 jsはtype="text/javascript"language="javascript"が受け付けられるみたいです。 (ブログを記入した時点:2023-04-02)

wshを必ずcscriptで実行する

いろいろな仕掛けが満載なのですが、とりあえず結果を見てみましょう。

【wsfの例】 ... sample_wsh4.wsfで保存&実行してみましょう
※以下のscript要素の中身はjavascriptで書いていきます。

<?xml version="1.0" encoding="UTF-8" ?>
<package>
    <job id='start'>
        <script type="text/javascript">
            var wss = new ActiveXObject("WScript.Shell");
            wss.Run('cmd /k  cscript //nologo  //job:main  ' + WScript.ScriptFullName, 1, false);
        </script>
    </job>
    <job id='main'>
        <script type="text/javascript">
            WScript.echo("hello!!");
        </script>
    </job>
</package>

スクリプトの実行結果は以下のような感じです。

wshを必ずcscriptで実行する方法の解説

  • <?xml version="1.0" encoding="UTF-8" ?>
    wsfファイルは基本的にxml形式なのでトラブル防止のためにおまじないを書いておく。

  • <package></package>
    複数のjobを記述する場合は、<package></package>で囲む必要があります。

  • <job id='start'><job id='main'>
    複数のjobを使い分ける場合には、jobを識別するためのidを設定する必要がある。
    cscriptのコマンドラインオプションに//job:mainの様に書いて実行するjobを指示できる。
    cscriptのコマンドラインオプションでjobを指示しない場合は先頭に書いたjobが実行される。
    上記サンプル sample_wsh4.wsf の場合は //job:start を指示するのと同じである。

job id='start' の解説

もう少しでゴールが見えてきました。

  • var wss = new ActiveXObject("WScript.Shell");
    //job:startから//job:mainを起動するためにActiveXObjectオブジェクトを準備しています。
    wshで準備されて使用できるWScriptオブジェクトとActiveXObject(WScript.Shell)が全く同じ綴りなので混同しそうになりますが別モノなので注意しましょう。

  • wss.Run( 実行文字列 , 1, false);
    ActiveXObject(WScript.Shell)のrunメソッドで別プロセスを起動している。

    • 別プロセスの実行文字列(引数1)
    • ウィンドウ通常アクティブ(引数2)
    • 終了待ち無し(引数3)
  • 実行文字列(前)
    'cmd /k cscript

    • cmd.exeでcscript.exeを実行
    • cscript.exe終了後にプロンプトで待つ
  • 実行文字列(後)
    //nologo //job:main ' + WScript.ScriptFullName
    cscript.exeの引数です。

    • cscript.exe起動時のロゴを無しにしています。
    • cscript.exeで実行するjobを指示しています。
    • cscript.exeで実行するwsfを指示しています。
      wshで準備されて使用できるWScriptオブジェクトから、実行中のスクリプトのファイル名をフルパスで得ています。

job id='main' の解説

※前半で説明した通り「hello!!」を出力する記述です。

まとめ

これでexplorerでダブルクリックしたスクリプト(.wsfファイル)がコマンドプロンプトで実行される様になりました。

参考

リファレンス | Microsoft Learn