2010-11-30 59 views
3

我正在开发一个具有Objective-C守护程序的Cocoa GUI应用程序。守护进程由LaunchDaemon启动,GUI使用每个用户的loginItems启动。从根帐户启动应用程序

当更新部署时,我需要更新守护进程,这很简单,并更新GUI。我希望能够退出GUI,替换应用程序,并在当前正在运行的每个用户帐户上重新启动它。我想从守护进程中完成所有这些,当然这是以root身份运行的。

我该如何: 1)以root用户身份退出,然后在另一个用户界面重新启动应用程序? 2)以root用户身份退出,然后为当前登录的每个用户重新启动一个特定的loginItem?

我尝试过搜索,并且有很多讨论,包括similar question,但似乎没有可用的工作解决方案。

任何帮助,非常感谢。

回答

3

所以我用一个支持请求与苹果得到最好的答案,与一些在线调查相结合。

攻击的基本计划是让每个GUI实例在守护进程告诉它时自行重启。

首先,我让守护程序替换GUI的包(.app文件夹)。您可以在应用程序仍在运行时执行此操作。这正是Apple支持帮助的地方。我仍然感到惊讶的是,一个应用程序可以在运行时被替换,但他们告诉我这样做,那样会好的。

然后我让守护进程启动了一个DistributedNotification到GUI并带有一条消息来重启它自己。为了让GUI能够正确响应,我创建了restarter类,它将获取它自己的pid和bundle路径,然后我在内存中构建了一个shell脚本,它杀死了pid,等了10秒钟,然后执行了一个shell“open bundlepath.app”重新启动。

我用NSTask调用 “内存” 中的shell脚本,这真的只是一个@ “杀%@;睡10;打开%@”,PID,bundlePath ....

工作得!

感谢您的建议!

0

在Apple的文档中查找“授权服务”。

+0

谢谢,我已经看过“授权服务”,正如你所提到的,但它似乎是用来提升根权限。我已经在后台以root用户身份运行,需要从我的根特权后台任务启动用户登录会话中的应用程序。 – Dave 2010-12-01 14:31:37

3

我相信NSDistributedNotificationCenter应该为此工作。请注意,使用NSDistributedNotificationCenter在不同用户帐户中的进程之间进行通信本身并不需要root权限。

为了帮助用户帐户之间的协调,它可能有助于区分GUI应用程序和守护程序当前处于活动状态和处于控制状态的哪个实例以及哪些实例是被动的。您可以使用NSWorkspace的通知(NSWorkspaceSessionDidBecomeActiveNotification,NSWorkspaceSessionDidResignActiveNotification)来确定用户何时在用户帐户之间切换,并让您的实例相应地进行设置。

假设您的GUI应用程序和守护程序在3个不同的用户帐户中运行实例。例如,如果在活动用户帐户中想要开始更新过程,则可以使用NSDistributedNotificationCenter轻松地告知所有其他实例立即关闭。要做到这一点,你需要定义如下的内容。

在.h文件中,声明你通知不同的名称:

extern NSString * const MDShouldTerminateImmediatelyNotification; 
在(一)实现文件

,创建名称,并设置等级可达感兴趣由分布式通知名字,等:

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类型进程(后台进程,以用户级别运行,每个用户帐户都有自己的实例)。

欲了解更多信息:

Technical Note TN2083 Daemons and Agents

Root and Login Sessions

Creating launchd Daemons and Agents

+0

谢谢你。现在我有很多阅读资料!我正在使用分布式对象进行通信。有一个守护程序实例,并且可能是每个用户的GUI实例。我可以通过发送通知让GUI退出,但这不是真正的问题。真正的问题是,一旦守护程序指示GUI退出并更新实际的GUI应用程序包,如何让守护程序重新启动GUI的所有实例而不打扰用户? - 我正在阅读你的链接,看看我能否在那里找到一些东西。再次感谢。 – Dave 2010-12-01 17:15:11

相关问题