3

Objective-C デーモンを持つ Cocoa GUI アプリを開発しています。デーモンは LaunchDaemon によって起動され、GUI は各ユーザーの loginItems を使用して起動されます。

アップデートが展開されたら、単純なデーモンをアップデートし、GUI をアップデートする必要があります。GUI を終了し、アプリを置き換えて、現在実行中の各ユーザー アカウントでアプリを再起動できるようにしたいと考えています。もちろん、ルートとして実行されているデーモンからこれらすべてを実行したいと思います。

1) root としてアプリを終了し、別のユーザーのインターフェイスでアプリを再起動するにはどうすればよいですか? 2)ルートとして、現在ログインしている各ユーザーの特定のloginItemを終了してから再起動しますか?

検索してみましたが、この同様の質問を含む多くの議論がありますが、有効な解決策はないようです。

どんな助けでも大歓迎です。

4

3 に答える 3

3

これには NSDistributedNotificationCenter が機能するはずです。NSDistributedNotificationCenter を使用して異なるユーザー アカウントのプロセス間で通信すること自体は、ルート権限を必要としないことに注意してください。

ユーザー アカウント間の調整を支援するために、現在アクティブで制御されている GUI アプリとデーモンのインスタンスと、パッシブなインスタンスを区別すると役立つ場合があります。NSWorkspace の通知 (NSWorkspaceSessionDidBecomeActiveNotification、NSWorkspaceSessionDidResignActiveNotification) を使用して、ユーザーがいつユーザー アカウントを切り替えたかなどを判断し、それに応じてインスタンスを設定することができます。

GUI アプリとデーモンに、3 つの異なるユーザー アカウントで実行されているインスタンスがあるとします。アクティブなユーザー アカウントで更新プロセスを開始する場合は、NSDistributedNotificationCenter を使用して、たとえば、他のすべてのインスタンスをすぐにシャットダウンするように簡単に指示できます。そのためには、次のように定義します。

.h ファイルで、さまざまな通知の名前を宣言します。

extern NSString * const MDShouldTerminateImmediatelyNotification;

(an)実装ファイルで、名前を作成し、その名前による分散通知に関心を持つようにクラスを設定します。

NSString * const MDShouldTerminateImmediatelyNotification = @"MDShouldTerminateImmediately";


- (id)init {
   if (self = [super init]) {
       [[NSDistributedNotificationCenter defaultCenter]
       addObserver:self
       selector:@selector(shouldTerminateImmediately:)
       name:MDShouldTerminateImmediatelyNotification
       object:nil];
   }
   return self;
}

- (void)dealloc {
   [[NSDistributedNotificationCenter defaultCenter] removeObserver:self];
   [super dealloc];
}

- (void)shouldTerminateImmediately:(NSNotification *)notification {
   if (ourInstanceIsInControl == NO) {
     [NSApp terminate:nil];
    }
}

更新プロセスを開始するクラスでは、次のようにして通知を送信します。

- (void)beginUpdate {
   [[NSDistributedNotificationCenter defaultCenter]
    postNotificationName:MDShouldTerminateImmediatelyNotification
       object:[self description] // or just nil
       userInfo:nil
       options:NSNotificationDeliverImmediately | NSNotificationPostToAllSessions];
    // continue

}

少なくとも、それは取り組みの始まりになるはずだと思います....

実際、すべてのユーザー アカウントですべてを行う root として実行される単一のデーモン インスタンスについて話している場合は、その部分を Launchd Agent タイプのプロセス (バックグラウンド プロセス、ユーザー レベルで実行、各ユーザー アカウントで実行) に分割することを検討する必要がある場合があります。独自のインスタンスがあります)。

詳細については:

テクニカル ノート TN2083 デーモンとエージェント

ルートおよびログイン セッション

launchd デーモンとエージェントの作成

于 2010-12-01T15:52:51.897 に答える
3

そこで私は、Apple にサポート リクエストを送信して最良の回答を得るとともに、いくつかのオンライン調査を組み合わせました。

攻撃の基本的な計画は、デーモンが指示したときに各 GUI インスタンスを再起動させることでした。

まず、デーモンに GUI のバンドル (.app フォルダー) を置き換えさせました。アプリがまだ驚くほど実行されている間にこれを行うことができます. そこで助けになったのが Apple サポートです。アプリを実行中に置き換えることができることに今でも驚いていますが、これを行うように言われ、問題ないと言われました。

次に、デーモンが GUI に DistributedNotification を起動し、それ自体を再起動するようにメッセージを表示しました。GUI が正しく応答するようにするために、独自の pid とバンドル パスを取得するリスタータ クラスを作成し、メモリ内に pid を強制終了するシェル スクリプトを作成し、10 秒待ってからシェル「open bundlepath.app」を実行し、それを実行しました。再開しました。

私は NSTask を使用して「メモリ内」シェル スクリプトを呼び出しましたが、これは実際には @"kill %@; sleep 10; open %@", pid, bundlePath...

驚くほど機能します!

ご提案いただきありがとうございます。

于 2010-12-17T13:51:50.890 に答える
0

Apple のドキュメントで「認証サービス」を探してください。

于 2010-12-01T00:24:15.177 に答える