第26話:WSHを利用したローカルアプリケーション

第5部 応用編

目次

マンガ

マンガ

マンガ

マンガ

マンガ

マンガ

マンガ

マンガ

マンガ台詞

【1Page】
アイコン先生:今回はWindows向けの
    ローカルアプリケーションを JavaScriptで手軽に作るぞ
アイコン遊:ローカルアプリケーション?
アイコン先生:EXEファイルみたいに ダブルクリックで実行したり
    ドラッグ&ドロップで 起動したりするソフトだ
アイコン守:Node.jsの プログラムみたいな ものですか?
アイコン先生:もう少し簡単に作れる 『WSH』を使うんだ
        WSH = Windows Script Host
    というわけで 俺が作った テンプレート を示すぞ
【2Page】
        【sample.wsf】
        <job id="main">
            <script language="JavaScript" src="cmnFunc.js"></script>
            <script language="JavaScript">
                // グローバル変数
                var args;               // 引数
                var dropFilePath = "";  // ドロップ ファイルのパス
                var dropFileStr  = "";  // ドロップ ファイルの中身の文字列

                // メイン ルーチン
                init();         // 初期化処理
                main();         // メイン処理

                // 初期化処理
                function init() {
                    args = WScript.Arguments;   // 引数のオブジェクト
                    if (args.length >= 1) {
                        dropFilePath = args(0);
                        dropFileStr  = cmnFunc.readFile(dropFilePath);
                    }
                }

                // メイン処理
                function main() {
                    if (dropFilePath == "") {
                        WScript.Echo("ドロップ ファイルなし");
                    } else {
                        WScript.Echo(dropFilePath + "\n" + dropFileStr);
                    }
                }
            </script>
        </job>
【3Page】
アイコン先生:ダブルクリックで アラートが出る
        sample.wsf
        ドロップ ファイルなし
    ファイルをドロップすれば 中身を表示する
        sample.wsf
        紹介.txt
        安見遊は体を動かしたくない面倒くさがり屋の女の子
    このソースを見て 気付いた点はあるか?
アイコン守:『<job>』や『<script>』 というタグがありますね
    なんだかHTMLファイルみたいです
        <job id="main">~</job>
        <script language="JavaScript">~</script>
アイコン麗:あと『cmnFunc.js』という 外部ファイルも 読み込んでいますね
    これもHTMLファイルに 似ています
        <script language="JavaScript" src="cmnFunc.js"></script>
【4Page】
アイコン遊:でも これって HTMLファイルじゃ 見ないわよ
    それに『WScript』という 変なものもあるし
        WScript.Echo("ドロップ ファイルなし");
アイコン先生:みんな いいところに 気が付いた
    Webページのプログラムでは 『window』オブジェクトを利用した
    WSHのプログラムでは 『WScript』オブジェクトを利用する
        // 例)ダイアログの出し方の違い
        window.alert("文字列");        // Webページ
        WScript.Echo("文字列");        // WSH
アイコン守:なるほど ところで 『cmnFunc.js』には 何が入っているん ですか?
アイコン先生:これもソースを 示しておこう
【5Page】
        【cmnFunc.js】
        var cmnFunc = new function() {
            // オブジェクトの作成
            this.createObject = function(name) {
                return WScript.CreateObject(name);
            };

            // WScriptのシェル
            // ファイル システム オブジェクト
            // 実行ファイルのパス
            // ルート ディレクトリ
            this.wshell = this.createObject("WScript.Shell");
            this.fs = this.createObject("Scripting.FileSystemObject");
            this.rootPath = WScript.ScriptFullName;
            this.rootDir = this.fs.GetFile(this.rootPath).ParentFolder;

            // ファイルに文字列を書き込み
            this.writeFile = function(path, data) {
                var stream = this.fs.CreateTextFile(path, true);
                stream.Write(data);
                stream.Close();
            };

            // ファイルから文字列を読み込み
            this.readFile = function(path) {
                if (this.fs.FileExists(path) == 0) return "";
                var stream = this.fs.OpenTextFile(path, 1);
                var rdStr = "";
                try {rdStr = stream.ReadAll();} catch(e){}
                stream.Close();
                return rdStr;
            };
        }
【6Page】
アイコン先生:ファイル入出力 の関数を 用意しておいた
    このテンプレート を利用すれば 簡単にソフトが できるぞ
アイコン麗:あの 先生
    テンプレートを見ても どんなソフトを 作れるか分かりません
アイコン先生:あー そうか
    これまでの プログラムとは 大きく違うからな
    よし どんなものが 作れるか 例を挙げよう
        テキストファイルを HTMLファイルに変換するツール
        ファイル内の 漢字 平仮名 片仮名の数を 調査するツール
    『sample.wsf』の 『メイン処理』を 書き換えれば
    いろいろなソフト を作れるぞ
        function main() {~}
アイコン遊:はいはいはーい
    作ったわ!
アイコン先生:早いな 何を 作ったんだ?
アイコン遊:ファイルを 暗号化する ツールよ
【7Page】
アイコン先生:おっ 凄いじゃないか
    どれどれ
        (10KBのテキストをドロップ。1KBになる)
        yuuApli.wsf
        紹介.txt  10KB
        yuuApli.wsf
        紹介.txt  1KB
    うん?
        (ダブルクリック)
        紹介.txt  1KB
        紹介.txt
        ファイル(F)  編集(E)  書式(O)
        暗号化
    おい ファイルの中に 『暗号化』と書いた だけじゃないか
アイコン遊:どう?
    中身が絶対にばれないわよ!
    (自信ありげ)
アイコン先生:はー
    プログラムの 技術がついても
    頭はよくならないな

説明

この章では、『WSHを利用したローカルアプリケーション』について学びます。

Windowsパソコンには、JavaScriptを使ってローカルアプリケーションを作成する仕組みが用意されています。それが『WSH』です。この『WSH』を利用したアプリケーションの作成には、これまで学んだJavaScriptの知識を利用することができます。

Windows専用のものなので、作成するプログラムの文字コードはShift_JISになります。

それでは以下、『WSH』を利用したアプリケーションの作成方法を紹介していきます。

『WSH』とは?

『WSH』(Windows Script Host)は、テキストファイルに書いたプログラムを実行する、Windows上の環境です。

『WSH』では、『VBScript』と『JavaScript』(正確にはJScript)が標準で利用できます。

本講座では、JavaScriptでプログラムを行っていきます。

『WSF』とは?

Windowsでは、拡張子『.js』のファイルをダブルクリックすることで、JavaScriptで書かれた『WSH』のプログラムを実行できます。

しかし、この拡張子『.js』のファイルは、正しく実行できないことがあります。これは、インストールしているソフトによって、関連付けが変更されているのが原因です。

関連付けというのは、どの拡張子のファイルを、どのソフトで開くかという設定です。Windowsでは、拡張子とソフトを対応させています。そして、ファイルをダブルクリックすると、特定のソフトで開くようにしています。

そのため、関連付けが変更されると、ファイルを実行しても、意図した動作にならないことがあります。拡張子『.js』のファイルは、Webサイト構築ソフトなどによって、関連付けが変更されていることがよくあります。

本講座では、この拡張子『.js』のファイルではなく、XML形式(HTMLのようにタグが付いたテキストファイル)でスクリプトを記述する『WSF』(Windows Script File)を利用します。

『WSF』では、ファイルの拡張子を『.wsf』とします。このファイルをダブルクリックしたり、このファイルに他のファイルをドロップすることで、『WSH』のプログラムを実行できます。

『WSF』の書き方

『WSF』のファイルは、『』とうタグで全体を囲います。以下、基本的な構造です。

<job id="main">
    <script language="JavaScript">
        // プログラム
    </script>
</job>

また、文字化けなどで正しく動作しない場合は、文字コードを明示的に指定することもできます。

<?xml version="1.0" encoding="shift-jis" ?>
<job id="main">
    <script language="JavaScript">
        // プログラム
    </script>
</job>
参考

『WSH』のテンプレート

マンガで出てきた『WSH』のテンプレートについて解説を行います。以下、『sample.wsf』のソースコードです。

<job id="main">
    <script language="JavaScript" src="cmnFunc.js"></script>
    <script language="JavaScript">
        // グローバル変数
        var args;               // 引数
        var dropFilePath = "";  // ドロップ ファイルのパス
        var dropFileStr  = "";  // ドロップ ファイルの中身の文字列

        // メイン ルーチン
        init();         // 初期化処理
        main();         // メイン処理

        // 初期化処理
        function init() {
            args = WScript.Arguments;   // 引数のオブジェクト
            if (args.length >= 1) {
                dropFilePath = args(0);
                dropFileStr  = cmnFunc.readFile(dropFilePath);
            }
        }

        // メイン処理
        function main() {
            if (dropFilePath == "") {
                WScript.Echo("ドロップ ファイルなし");
            } else {
                WScript.Echo(dropFilePath + "\n" + dropFileStr);
            }
        }
    </script>
</job>

先ほど説明したとおり、全体を『<job id="main">~</job>』と囲い、その中に『<script>』タグを使ってプログラムを書いています。

『src="cmnFunc.js"』として読み込んでいる『cmnFunc.js』は、本講座用に用意した共通関数を収録した、外部JavaScriptファイルです。このファイルには、ファイルの入出力を行うための関数を収録しています。

それでは以下、起動してから行われる処理を順番に見て行きます。

ダブルクリック、もしくはファイルのドロップで起動した『sample.wsf』は、『メイン ルーチン』の2つの関数を実行します。まずは『init』という初期化処理を行う関数を実行します。そして次に、『main』というメイン処理を行う関数を実行します。

初期化処理

『init』内で行う初期化処理では、『WScript.Arguments』という、引数を表すオブジェクトを、変数『arg』に入れています。

これまで出てきた『関数の引数』は、関数のあとの括弧内に書かれる変数でした。『ファイル実行時の引数』は、実行ファイルにドロップした『ファイルのパス』になります。『sample.wsf』に『紹介.txt』というファイルをドロップした場合は、『紹介.txt』のフルパス(完全なパス)が、引数になります。

この引数の数が1以上の場合は、『ファイル実行時の引数』が存在します。そこで、『if (args.length >= 1)』と引数の数を確認して、『1』以上ならば『dropFilePath = args(0)』として、引数を取り出しています。そして、このファイルのパスを元にして、『cmnFunc.readFile』メソッドを利用して、ファイルの中身を変数『dropFileStr』に読み込んでいます。

メイン処理

メイン処理では、ドロップファイルのパスがあるかどうかで、処理を分岐させています。

ドロップファイルのパスが空の場合は、ダイアログを開いて、『ドロップ ファイルなし』と表示させています。また、ドロップファイルのパスが存在する場合は、ダイアログを開いて、ドロップファイルのパスと、その中身の文字列を表示させています。

ここで注意するのは『WScript.Echo』メソッドです。『WSH』のプログラムでは、Webページのプログラムと違って『window』オブジェクトが存在しません。そのために『window.alert』メソッドもありません。また、『window.document』といったオブジェクトも利用できません。

『WSH』のプログラムでは、『window』オブジェクトの代わりに『WScript』オブジェクトを利用します。このオブジェクトには『Echo』という、『alert』のようにダイアログを表示するメソッドが用意されています。そこでこの『Echo』メソッドを利用して、ダイアログを表示します。

『cmnFunc.js』

『cmnFunc.js』についても、ソースを示します。こちらは少し高度ですので、理解できない場合は読み飛ばしても構いません。この『cmnFunc.js』のように、外部JavaScriptファイルとして利用するプログラムは、中身を理解していなくても利用できます。

var cmnFunc = new function() {
    // オブジェクトの作成
    this.createObject = function(name) {
        return WScript.CreateObject(name);
    };

    // WScriptのシェル
    // ファイル システム オブジェクト
    // 実行ファイルのパス
    // ルート ディレクトリ
    this.wshell = this.createObject("WScript.Shell");
    this.fs = this.createObject("Scripting.FileSystemObject");
    this.rootPath = WScript.ScriptFullName;
    this.rootDir = this.fs.GetFile(this.rootPath).ParentFolder;

    // ファイルに文字列を書き込み
    this.writeFile = function(path, data) {
        var stream = this.fs.CreateTextFile(path, true);
        stream.Write(data);
        stream.Close();
    };

    // ファイルから文字列を読み込み
    this.readFile = function(path) {
        if (this.fs.FileExists(path) == 0) return "";
        var stream = this.fs.OpenTextFile(path, 1);
        var rdStr = "";
        try {rdStr = stream.ReadAll();} catch(e){}
        stream.Close();
        return rdStr;
    };
}

以下、プログラム自体の解説は高度になるので、使い方だけを示します。

『<script language="JavaScript" src="cmnFunc.js"></script>』としてファイルを読み込んだあと、以下のメソッドを利用することができます。

書き方 引数 戻り値 説明
cmnFunc.readFile(path) 『path』は、読み込むファイルのパス 読み込んだ
ファイルの文字列
ファイルを文字列
として読み込む
cmnFunc.writeFile(path, data) 『path』は、書き込むファイルのパス
『data』は、書き込む内容
なし ファイルに文字列を
上書きする

また、『cmnFunc』では、以下のプロパティを利用できます。

書き方 説明
cmnFunc.rootPath 『cmnFunc.js』のフルパス
cmnFunc.rootDir 『cmnFunc.js』の保存されているディレクトリ
cmnFunc.wshell OSのシェルを操作するオブジェクト
cmnFunc.fs ファイル システム オブジェクト

『WScript』と『ActiveXObject』

『WSH』のプログラミングでは、OSの機能を利用したり、ファイルの入出力を行ったりできます。また、『ActiveX』と呼ばれる一連のオブジェクトを利用して、様々な処理を行えます。

『WSH』では、『WScript』が、Webページのプログラミングでの『window』のような、基本のオブジェクトになっています。

例えばダイアログ表示は、Webページでは『window.alert』でしたが、『WSH』では『WSH.Echo』になります。

// Webページ
window.alert("message");

// 『WSH』
WSH.Echo("message");

『WScript』から呼び出せる様々なオブジェクト

こういった違いの他に、『WSH』のプログラミングでは、様々なオブジェクトを『WScript』から呼び出せます。

var wshell = WScript.CreateObject("WScript.Shell");
var fs = WScript.CreateObject("Scripting.FileSystemObject");

1行目のプログラムでは、『WScript』を利用して『WScript.Shell』という、シェル(OS)を操作するオブジェクトを呼び出しています。

2行目のプログラムでは、同様に『Scripting.FileSystemObject』という、ファイルを操作するオブジェクトを呼び出しています。

『ActiveX』オブジェクト

オブジェクトの呼び出しは、『WScript』以外から行われることもあります。『ActiveX』と呼ばれる一連のオブジェクトを利用する場合は『new ActiveXObject()』として呼び出します。

var ado = new ActiveXObject("ADODB.Stream");

『WSH』で利用できるオブジェクトは無数にあります。行いたい処理に合わせて、どんなオブジェクトを利用できるか、ネットや本で調べてください。

『WSH』を利用したアプリケーションの実例

以下、『WSH』を利用して、Yahoo!ニュースのRSSをダウンロードするプログラムの実例を示します。参考にして、各自便利なプログラムを作成してください。

以下、『sample2.wsf』のソースコードです。『sample2.wsf』をダブルクリックすれば、Yahoo!ニュースのRSS『https://dailynews.yahoo.co.jp/fc/rss.xml』を取得して、ローカルに保存します。また、保存したフォルダをExplorerで開きます。

少し高度になりますが、このプログラムの意味が全て分かれば、JavaScriptの腕前はかなりのレベルに到達していると言えるでしょう。

<job id="main">
    <script language="JavaScript" src="cmnFunc.js"></script>
    <script language="JavaScript" src="cmnFunc.exec.js"></script>
    <script language="JavaScript" src="cmnFunc.download.js"></script>
    <script language="JavaScript">
        // メイン ルーチン
        main();         // メイン処理

        // メイン処理
        function main() {
            var resText = cmnFunc.download(
                "https://news.yahoo.co.jp/pickup/rss.xml",
                "dailynews_yahoo_rss.xml"
            );
            WScript.Echo("取得した文字列の長さ : " + resText.length);
            cmnFunc.run("explorer.exe", cmnFunc.rootDir);
        }
    </script>
</job>

以下、『cmnFunc.js』です。

var cmnFunc = new function() {
    // オブジェクトの作成
    this.createObject = function(name) {
        return WScript.CreateObject(name);
    };

    // WScriptのシェル
    // ファイル システム オブジェクト
    // 実行ファイルのパス
    // ルート ディレクトリ
    this.wshell = this.createObject("WScript.Shell");
    this.fs = this.createObject("Scripting.FileSystemObject");
    this.rootPath = WScript.ScriptFullName;
    this.rootDir = this.fs.GetFile(this.rootPath).ParentFolder;

    // ファイルに文字列を書き込み
    this.writeFile = function(path, data) {
        var stream = this.fs.CreateTextFile(path, true);
        stream.Write(data);
        stream.Close();
    };

    // ファイルから文字列を読み込み
    this.readFile = function(path) {
        if (this.fs.FileExists(path) == 0) return "";
        var stream = this.fs.OpenTextFile(path, 1);
        var rdStr = "";
        try {rdStr = stream.ReadAll();} catch(e){}
        stream.Close();
        return rdStr;
    };
}

以下、『cmnFunc.run.js』です。

// 先に『cmnFunc.js』を読み込んでおく
if (typeof(cmnFunc) != "undefined") {
    // EXEを実行
    // 引数1:『path』実行ファイルのパス。もしくは、開きたいファイル
    // 引数2:『option』引数1で実行ファイルを指定した場合の起動オプション
    // 引数3:『wait』0なら待機なし、1なら待機あり、デフォルト0
    cmnFunc.run = function(path, option, wait) {
        if (wait != 0 && wait != 1) wait = 0;
        try {
            var runPath = '"' + path + '"';
            if (option != "") runPath += ' "' + option + '"';
            this.wshell.Run(runPath, 10, wait);
        } catch(e) {
            var runPath = path;
            if (option != "") runPath += ' ' + option;
            this.wshell.Run(runPath, 10, wait);
        }
    }
}

以下、『cmnFunc.download.js』です。

// 先に『cmnFunc.js』を読み込んでおく
if (typeof(cmnFunc) != "undefined") {
    // EXEを実行
    // 引数1:『url』ダウンロードするファイルのURL
    // 引数2:『path』保存ファイル名、もしくはパス、空時は保存なし
    // 戻り値:テキストの場合は文字列、失敗時は『err』
    cmnFunc.download = function(url, path) {
        var progIDs = [
            "Msxml2.ServerXMLHTTP.6.0",
            "Msxml2.ServerXMLHTTP.5.0",
            "Msxml2.ServerXMLHTTP.4.0",
            "Msxml2.ServerXMLHTTP.3.0",
            "Msxml2.ServerXMLHTTP",
            "Microsoft.ServerXMLHTTP",
            "Msxml2.XMLHTTP.6.0",
            "Msxml2.XMLHTTP.5.0",
            "Msxml2.XMLHTTP.4.0",
            "Msxml2.XMLHTTP.3.0",
            "Msxml2.XMLHTTP",
            "Microsoft.XMLHTTP"
        ]; 

        var xmlHttp;
        var resText;
        var resBody;
        for (var i = 0; i < progIDs.length; i ++) {
            try {
                xmlHttp = new ActiveXObject(progIDs[i]);
                if (typeof(xmlHttp) == "undefined") break;
            } catch(e){}
        }
        if (typeof(xmlHttp) == "undefined") return "err";

        try {
            xmlHttp.open("GET", url, 0);    // 0 : 同期処理
            xmlHttp.send("");
            resText = xmlHttp.responseText;
            resBody = xmlHttp.responseBody;
        } catch(e){}
        xmlHttp = null;
        if (path == "") return resText;

        var ado;
        try {
            ado = new ActiveXObject("ADODB.Stream");
            ado.Type = 1;   // 1 : バイナリ
            ado.open()
            ado.write(resBody)
            ado.saveToFile(path, 2);    // 2 : 上書き保存
            ado.close();
            ado = null;
        } catch(e){
            if (ado != null) {
                try {ado.close();} catch(e){}
                ado = null;
            }
            return "err";
        }
        return resText;
    }
}

サンプルの入手

以下は、今回出てきたサンプルです。

ZIPでまとめてダウンロード (右クリックから保存してください)

sample.wsf』(テンプレート)(右クリックから保存してください)

cmnFunc.js』(共通関数)(右クリックから保存してください)

sample2.wsf』(ニュースのRSSをダウンロード)(右クリックから保存してください)

cmnFunc.run.js』(ファイルを実行関数)(右クリックから保存してください)

cmnFunc.download.js』(ダウンロード関数)(右クリックから保存してください)

プログラムの中身を見たい場合は、それぞれのHTMLファイルをブラウザで開いたあと、右クリックをして『ソースの表示』を選択してください。

メモ帳で、ファイルの中身を見ることができます。