2017-03-04 5 views
1

.appバンドルのすぐ外側のフォルダにリソースをロードするアプリケーションのmacOSバイナリをパッケージ化しました。ディレクトリ構造がC++ macOSアプリケーションでの.appバンドルの場所へのchdir

Foo/ 
    Foo.app/ 
     Contents/ 
      ... 
    resources/ 

のように見える私は親ディレクトリFoo/にアプリケーションの作業ディレクトリを変更したい、これは私がこれまでに出ているものです。

#if defined(APPLE) 
    #include "CoreFoundation/CoreFoundation.h" 
    #include <unistd.h> 
    #include <libgen.h> 
#endif 


int main() { 
#if defined(APPLE) 
    // macOS workaround for setting the working directory to the location of the .app 
    { 
     CFBundleRef bundle = CFBundleGetMainBundle(); 
     CFURLRef bundleURL = CFBundleCopyBundleURL(bundle); 
     char path[PATH_MAX]; 
     Boolean success = CFURLGetFileSystemRepresentation(bundleURL, TRUE, (UInt8 *)path, PATH_MAX); 
     assert(success); 
     CFRelease(bundleURL); 

     chdir(dirname(path)); 
    } 
#endif 

    ... 
} 

これは、(私がテストしているすべてである)のMacOS 10.7と10.10上で動作するように見えますが、10.12に、ユーザーがリソースがロードされていないので、私は上記のハックもはや作品と思われることを報告しています正しく

実行されている.appバンドルのディレクトリに変更するより良い方法はありますか?

答えて

2

アプリケーションバンドルの外部からのリソースのロードは、セキュリティ上の脆弱性です。 Appleはそれを防ぐために10.12でapp translocation(a.k.a path randomization)を実装しています。彼らの推奨する解決策は、署名付きのディスクイメージであなたのアプリを出荷することです。 hereを参照してください:MacOSの10.12で開始

、あなたは、もはやzipアーカイブまたは符号なしのディスクイメージでコード署名アプリと一緒に外部コードやデータを提供することはできません。 Mac App Storeの外に配布されるアプリは、起動時にランダムなパスから実行されるため、そのような外部リソースにアクセスすることはできません。安全な実行を提供するには、codesignツールを使用してディスクイメージ自体に署名を付けるか、Mac App Storeを通じてアプリを配布します。詳細については、macOS Code Signing In Depthの更新版を参照してください。

+0

Uggghhhh ...情報をありがとう!私はディスクイメージメソッドを試してみます。署名されたディスクイメージでは、上記のように 'Foo'ディレクトリ構造を持つことは可能ですか? – Vortico

+0

ディスクイメージは、ルートフォルダがFooフォルダと本質的に似ているボリュームとしてマウントされます。これには、アプリとその近隣のリソースの両方が含まれます。ユーザーは、両方をローカルファイルシステムに一緒にコピーする必要があります。これは保証することが難しいです。ディスクイメージに明示的なFooフォルダが含まれるようにすると、ユーザーがそのイメージをユニットとしてコピーするように促すことができますが、実際にユーザーが実際にそれを行う保証はありません。 –

+0

もう一つの選択肢は、ディスクイメージまたはzipアーカイブではなくインストーラパッケージを出荷することです。それはアプリケーションとそのリソースを、Fooフォルダに/ Applicationsの下に一緒にインストールします。最後に、これらのリソースをアプリバンドルに移動して、この問題全体を回避することを検討しましたか?アプリの外にあるリソースが最初はなぜですか? –

1

これは別の方法ですが、まだすべてのmacOSバージョンでテストしていません。私はこれが誰かを助けてくれることを願っていますが、私はそれが最良の方法であると判断するまで答えとして受け入れません。

#include <unistd.h> // for chdir 
#include <libgen.h> // for dirname 
#include <mach-o/dyld.h> // for _NSGetExecutablePath 
#include <limits.h> // for PATH_MAX? 

char path[PATH_MAX]; 
uint32_t pathLen = sizeof(path); 
int err = _NSGetExecutablePath(path, &pathLen); 
assert(!err); 

// Switch to the directory of the actual binary 
chdir(dirname(path)); 
// and then go up three directories to get to the folder of the .app bundle 
chdir("../../../"); 
+0

10.12以上でテストできましたか? – Warpspace

+0

隔離xattrが設定されている場合、アプリのトランスレーションにより、10.12以上では動作しません。考えられる回避策は、場所が/ Applications/YourAppNameであると仮定し、メッセージボックス経由で苦情を言い、その場所にアプリがインストールされていない場合は終了します。 – Vortico

関連する問題