Macで〜.appを実行する
ちょっと作ってみた。
Mac用のインターフェースでnsILocalFileMacというものが実はある。これをnsIFileに対して、QueryInterfaceするとisPackageというメソッドが使用可能になり、実行可能なパッケージであるか判定できる。
実装 - 1 : Info.plistファイルから実行ファイルを割り出す
パッケージのディレクトリ内、package/Contents/Info.plistというXMLファイルにそのパッケージの情報が書かれていて、<key>CFBundleExecutable</key>
に対応する string 要素に実行ファイル名が書かれている。それを使って実際に実行するファイルを割り出す方法。
// 実行例 execute("/Applications/Google Chrome.app", ["--", "http://example.com"]); var isMac = true; // 初期化時にMacかどうかの判定を行っておく。 function execute (path, args) { args = [].concat(args); var file = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsILocalFile); file.initWithPath(path); if (isMac) { file.QueryInterface(Ci.nsILocalFileMac); if (file.isPackage) { file = getExecuteFileFromPackage(file); } } var process = Cc["@mozilla.org/process/util;1"].createInstance(Ci.nsIProcess); process.init(file); process.run(false, args, args.length); } function getExecuteFileFromPackage (aFile) { var infoPlistFile = aFile.clone().QueryInterface(Ci.nsILocalFile); infoPlistFile.appendRelativePath("Contents/Info.plist"); var ifstream = Cc["@mozilla.org/network/file-input-stream;1"].createInstance(Ci.nsIFileInputStream); var domparser = Cc["@mozilla.org/xmlextras/domparser;1"].createInstance(Ci.nsIDOMParser); ifstream.init(infoPlistFile, -1, 0, 0); var doc = domparser.parseFromStream(ifstream, "UTF-8", infoPlistFile.fileSize, "application/xml"); ifstream.close(); var keys = doc.getElementsByTagName("key"); var exeFileName; for (var i = 0, key; key = keys[i]; i++){ if (key.textContent == "CFBundleExecutable") { exeFileName = key.nextElementSibling.textContent; break; } } var exeFile = aFile.clone().QueryInterface(Ci.nsILocalFile); exeFile.appendRelativePath("Contents/MacOS/" + exeFileName); return exeFile; }
getExecutableFileFromPackage
関数でInfo.plistファイルをパースして実行ファイルを取得している。(初めてDOMParserのparseFromStreamを使ったw)
ちょい面倒やね〜
実装 - 2 : /usr/bin/open に渡す
こちらは、実行パッケージだったら/usr/bin/openを実行ファイル、第一引数にパッケージのパスとなるように設定しなおす方法。
// 実行例 execute("/Applications/Google Chrome.app", ["--", "http://example.com"]); var isMac = true; // 初期化時にMacかどうかの判定を行っておく。 function execute (path, args) { args = [].concat(args); var file = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsILocalFile); file.initWithPath(path); if (isMac) { file.QueryInterface(Ci.nsILocalFileMac); if (file.isPackage) { args = [file.path, "--args"].concat(args); } file = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsILocalFile); file.initWithPath("/usr/bin/open"); } var process = Cc["@mozilla.org/process/util;1"].createInstance(Ci.nsIProcess); process.init(file); process.run(false, args, args.length); }
こっちの方がシンプルで良さそうな感じですね〜。