Mach3.laBlog

TitaniumDesktopの多重起動を抑制する(Windows)

この記事は賞味期限切れです。(更新から1年が経過しています)

最近Titaniumを少々いじっておりましたが、軽くハマったのでメモなど。
Titanium Desktopで作ったアプリの多重起動を抑制してみる実験。
環境の都合などで、Windowsのみ。

TitaniumDesktopの多重起動を抑制する(Windows)

概要

普通につくるといくらでも立ち上がるよ!

Titaniumで普通にデスクトップアプリを作ると、いくらでも立ち上げられます。
連打すれば連打しただけアプリウィンドウがぽぽぽぽーんと増えていく。
アプリの性格にもよりけりですが、不都合が生じる事の方が多そうです。

ざっくりとした仕組み

  1. タスクリストにある自分の名前の数を確認。
  2. 2個以上あったら多重起動されてしまっているので、自分を落とす。

ソース

見ての通り、Windows用の処理しか書いていません
Mac/Linuxではcaseを書き足してやらねば動きませんのでご注意を。

var SingleLaunch = function( appName, callback ){
    var name, args, prc;

    switch( Titanium.platform ){
        case "win32" : 
            name = appName + ".exe";
            args = [ "tasklist", "/NH", "/FI", "IMAGENAME eq " + name ];
            break;
        default :
            throw "このプラットフォームはサポートされていません";
            break;
    }
    prc = Titanium.Process.createProcess( args );
    prc.processCount = 0;
    prc.setOnRead(function(e){
        this.processCount += e.data.toString().match( RegExp( name, "g" ) ).length;
    });
    prc.setOnExit(function(){
        if( this.processCount >= 2 ){ 
            alert( appName + "は既に起動しています" );
            Titanium.UI.currentWindow.close();
            return;
        }
        callback();
    });
    prc.launch();
};

SingleLaunch( "YouApplication", function(){
    /* アプリを初期化 */
});

タスクリストを取得するには、Titanium.Processを使って「tasklist」コマンドを呼びます。
createProcessメソッドの引数に、コマンドとその引数を配列にして渡してlaunch

cf) Appcelerator Developer Center – API for Titanium.Process (version 1.1)

setOnReadは出力が返される度に呼ばれるので、そこで自分の名前を探して数を加算。
すべての出力が完了したらsetOnExitが呼ばれるので、合計の数を見て条件分岐します。
2個以上であれば自身を落とし、そうでなければcallbackを呼んでアプリの初期化を行いましょう。

ポイント

tasklistが正しい値を返してくれない

既に1個起動しているはずなのに自分の名前が見つからない。
Titanium.Processで呼んだtasklistと、コマンドプロンプトで呼んだtasklistで結果が変わってしまう。

どうやら、TitaniumProcessがヘッダの行数を勘違いしている事に起因する模様。
見出しを出力しない/HNオプションを付けることで解決出来ました。

args = [ "tasklist", "/NH", "/FI", "IMAGENAME eq " + name ];

exit()とclose()

アプリを終了するTitanium.App.exit()と、
現在のウィンドウを閉じるTitanium.UI.currentWindow.close()がありますが、
どのような違いがあって、どちらの方が良いのか、というお話。

試してみた結果、実行後即閉じるclose()に比べ、
exit()は終了処理的な事をしているらしく、かなり動作がモッサリとしています。
ただし、close()したらすぐにプロセスが消えるかというとそうではなく、
だいたいexit()と同じぐらい待たされてからタスクリストから姿を消します。

exit()の方が安心そうではありますが、
見た目だけでもサクッと閉じてほしいので、取り急ぎ今回はclose()を使っています。
(そう思わせる程度には、exitはモッサリしています)

まとめ

ひょっとしたら多重起動防止用の何かが既にあるかもしれないし、なくても今後実装されるかもしれませんが、
とりあえず情報が見つからなかったので書いてみました。ツッコミありましたらよろしく願います。

コメント

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

*

mach32ac00a19d261ed2dfb9c3434899a1ce9
<p>コメントありがとうございます。</p>

<p>手元にあったのが少々古いSDKでしたのでそちらで試しましたが、RegExp関連での問題はこちらでは生じませんでした。</p>

<p>当方で思いつく原因としては、Titanium DesktopのFileStreamでread()をコールして帰ってくる値が文字列型(String)ではないという点です。ファイル内容をread()で格納した後で、toString()すると動いたりはしないでしょうか?</p>
akaoru5154c7bb1380da596c2459fcfa029e2c
<p>こんにちわ。Titanium DesktopでRegExp関係に問題が出ませんか?例えば、何かのファイルを読み込んで、replace(/&#092;n/g,'')としても、反応無く、無視されました。何かご存知でしたら、ご教示いただければ幸いです。</p>