【问题标题】:How do I run code when a user agent process terminates?当用户代理进程终止时如何运行代码?
【发布时间】:2011-02-06 15:45:12
【问题描述】:

我想要什么

我想要一个帮助应用程序用户代理(Info.plist 中的 LSUIElement 为 True)在终止时将自身添加到登录项中。

问题

在帮助应用程序进程终止之前,我无法运行任何代码。 我的“添加到登录项”代码运行良好。

背景

  • 我有一个始终运行的帮助应用程序用户代理进程
  • 首次启动时,它会将自身添加到登录项中
  • 如果应用程序被移动,在下次登录时,辅助应用程序进程将找不到,因此不会启动

我的尝试

我想知道我是否应该继承 NSApplication 并覆盖 terminate: 或 stop: 并将我的代码放在那里,但这似乎有点过头了。肯定有更好的方法吗?

我在 NSApp 委托中尝试了所有这些不同的东西:

-(void)applicationWillTerminate:(NSApplication *)sender {
     [self addHelperAppToLoginItems]
}

-(void)applicationDidTerminate:(NSApplication *)sender {
     [self addHelperAppToLoginItems]
}

-(NSApplicationTerminateReply)applicationShouldTerminate:(NSApplication *)sender {
     [self addHelperAppToLoginItems]
}

-(void)applicationDidFinishLaunching:(NSNotification *)aNotification {
     [[[NSWorkspace sharedWorkspace] notificationCenter] addObserver:self 
                                                            selector:@selector(addHelperAppToLoginItems) 
                                                                name:NSWorkspaceDidTerminateApplicationNotification
                                                              object:nil];  

}

-(void)addHelperAppToLoginItems {
      // This code never gets called!
}

为什么 NSApplication 委托方法不适用于用户代理进程?

我怎样才能让进程在终止时检查登录项?

如果能提供任何帮助,我将不胜感激。谢谢!

11 年 6 月 2 日更新 1

经过进一步挖掘,问题更多的是进程永远不会真正退出,更常见的是它们被操作系统杀死。

这意味着当您选择“退出”活动监视器中的进程或关闭计算机时,不会调用终止委托方法。

运行以下 Applescript 时,会调用委托方法:

tell application "System Events"
    tell application "LapsusHelperApp"
         quit
    end tell
end tell

【问题讨论】:

  • 如果您的意思是在启动时将您的应用添加到登录项中,您为什么要在applicationWillTerminate: 中这样做?

标签: cocoa user-agent nsapplication


【解决方案1】:

经过进一步挖掘,问题更多的是进程永远不会真正退出,更常见的是它们被操作系统杀死。

这是因为您为您的应用程序启用了突然终止。它是可选的,因此只需从 Info.plist 中删除该键值对,您就会开始收到 applicationWillTerminate: 消息。

此外,Xcode 中的 Terminate 按钮(至少在 3.x 中)总是以与突然终止相同的方式工作,因此当您从 Xcode 中终止您的应用程序时,您永远不会收到 applicationWillTerminate: 消息。

顺便说一句:

  • applicationWillTerminate: 是一个通知消息,所以它的参数是一个 NSNotification 对象,而不是一个 NSApplication 对象。
  • 没有applicationDidTerminate:。片刻的反思将揭示原因。 ☺

【讨论】:

  • 谢谢,彼得,但是在为我的助手应用 Info.plist 添加一个布尔键 NSSupportsSuddenTermination 和值 NO 后,清理和重建,它似乎仍然没有得到 applicationWillTerminate:通知。我什至尝试在启动时致电[[NSProcessInfo processInfo] disableSuddenTermination],但仍然没有乐趣。任何想法为什么会这样?
  • 顺便说一下,您的建议适用于 LSUIElement 键为 NO 或 info.plist 中不存在的 Cocoa 应用程序。但是我的助手应用程序进程应该是一个用户代理,所以我使用的是 LSUIElementYES,并且使用此设置,我什至无法运行一个简单的 Xcode 项目来运行 applicationWillTerminate:
  • 无需显式禁用突然终止;正如我所说,它是可选的,这意味着默认情况下它被禁用。您必须明确启用它。如果您使用 Xcode 的 Terminate 命令,无论是否突然终止,都会终止您的应用程序。只有当您选择“强制退出”时,活动监视器才会这样做。除了注销之外,您通常如何退出您的应用程序?来自另一个进程(例如,系统偏好设置)的 Apple 事件?发送 NSApp terminate:?其他方式?
  • 不要忘记注销。如果您无论如何都需要在退出时发生这种情况(请参阅我对您问题的评论),请使用手册页中记录的 signalsigaction 函数捕获 SIGTERM。请注意,这意味着当您从 Xcode 中终止应用程序时,您的应用程序不会立即退出 - 如果 addHelperAppToLoginItems 损坏,可能会崩溃。
  • 感谢彼得提供所有这些详细信息。我将坚持将我的代码放在applicationWillTerminate:NSWorkspaceWillPowerOffNotification 中。顺便说一句,来自 Cocoa 文档中的此通知:“在用户请求注销或机器关闭时发布。”它现在在注销时运行良好。再次感谢!
猜你喜欢
  • 1970-01-01
  • 2011-12-04
  • 2019-08-01
  • 2018-03-31
  • 2018-11-14
  • 2011-06-21
  • 2019-01-11
  • 2017-04-06
  • 2021-11-22
相关资源
最近更新 更多