TitaniumDesktopの多重起動を抑制する(Windows)
この記事は賞味期限切れです。(更新から1年が経過しています)
最近Titaniumを少々いじっておりましたが、軽くハマったのでメモなど。
Titanium Desktopで作ったアプリの多重起動を抑制してみる実験。
環境の都合などで、Windowsのみ。
概要
普通につくるといくらでも立ち上がるよ!
Titaniumで普通にデスクトップアプリを作ると、いくらでも立ち上げられます。
連打すれば連打しただけアプリウィンドウがぽぽぽぽーんと増えていく。
アプリの性格にもよりけりですが、不都合が生じる事の方が多そうです。
ざっくりとした仕組み
- タスクリストにある自分の名前の数を確認。
- 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はモッサリしています)
まとめ
ひょっとしたら多重起動防止用の何かが既にあるかもしれないし、なくても今後実装されるかもしれませんが、
とりあえず情報が見つからなかったので書いてみました。ツッコミありましたらよろしく願います。
コメント
<p>手元にあったのが少々古いSDKでしたのでそちらで試しましたが、RegExp関連での問題はこちらでは生じませんでした。</p>
<p>当方で思いつく原因としては、Titanium DesktopのFileStreamでread()をコールして帰ってくる値が文字列型(String)ではないという点です。ファイル内容をread()で格納した後で、toString()すると動いたりはしないでしょうか?</p>