【问题标题】:Receiving power notifications (especially shutdown) on Mac OSX在 Mac OSX 上接收电源通知(尤其是关机)
【发布时间】:2009-08-24 08:57:22
【问题描述】:

我正在用 C 语言为 Mac (Leopard) 编写一个应用程序,它需要在接收电源通知时做一些工作,例如睡眠、唤醒、关机、重启。它在登录时通过launchd 作为启动代理运行,然后开始监视通知。我用来执行此操作的代码如下:

/* ask for power notifications */
static void StartPowerNotification(void)
{
    static io_connect_t rootPort;   
    IONotificationPortRef notificationPort;
    io_object_t notifier;

    rootPort = IORegisterForSystemPower(&rootPort, &notificationPort, 
                                        PowerCallback, &notifier);
    if (!rootPort) 
        exit (1);

    CFRunLoopAddSource (CFRunLoopGetCurrent(),  
                        IONotificationPortGetRunLoopSource(notificationPort), 
                        kCFRunLoopDefaultMode);
}

/* perform actions on receipt of power notifications */
void PowerCallback (void *rootPort, io_service_t y, 
                    natural_t msgType, void *msgArgument)
{
    switch (msgType) 
    {
        case kIOMessageSystemWillSleep:
            /* perform sleep actions */
            break;

        case kIOMessageSystemHasPoweredOn:
            /* perform wakeup actions */
            break;

        case kIOMessageSystemWillRestart:
            /* perform restart actions */
            break;

        case kIOMessageSystemWillPowerOff:
            /* perform shutdown actions */
            break;
    }
}

但是,只有睡眠和唤醒的前两个(kIOMessageSystemWillSleepkIOMessageSystemHasPoweredOn永远被调用。我从来没有收到任何重启或关机的通知(kIOMessageSystemWillRestartkIOMessageSystemWillPowerOff)。

我做错了吗?或者是否有另一个 API 可以给我重启和关闭通知?我更愿意将其保留为 C 程序(这就是我所熟悉的),但我愿意接受任何明智的替代建议(我已经查看了登录/注销挂钩,但这些似乎已被弃用)的发射)。

提前感谢任何帮助/提示!

【问题讨论】:

    标签: c macos shutdown


    【解决方案1】:

    我知道您可以从 NSWorkspace 注册 NSWorkspaceWillPowerOffNotification 通知,这不是 C 函数,但确实有效。

    #import <AppKit/AppKit.h>
    #import "WorkspaceResponder.h"
    
    int main (int argc, const char * argv[]) {
        NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
        NSNotificationCenter *nc = [[NSWorkspace sharedWorkspace] notificationCenter];
        WorkspaceResponder *mainController = [[WorkspaceResponder alloc] init];
    
        //register for shutdown notications
        [nc addObserver:mainController
    selector:@selector(computerWillShutDownNotification:)
              name:NSWorkspaceWillPowerOffNotification object:nil];
        [[NSRunLoop currentRunLoop] run];
        [pool release];
        return 0;
    }
    

    然后在 WorkspaceResponder.m 中:

    - (void) computerWillShutDownNotification:(NSNotification *)notification {
        NSLog(@"Received Shutdown Notification");
    }
    

    【讨论】:

    • 谢谢!您知道我是否需要窗口或停靠图标才能接收这些通知?
    • 再次感谢 Rob,非常感谢。
    • 我尝试了上述解决方案,但没有成功。将 Foundation 工具作为 LaunchDeamon 运行,但我链接 AppKit 只是为了尝试这个。似乎从来没有关闭过...这里不支持吗?
    • 这个答案中的代码看起来是正确的,但是通知不会被发送到一个守护进程——代码对于应用程序来说可以正常工作。
    • @IradK 如果您将其作为LaunchAgent 运行,而不是作为LaunchDaemon 运行,它将起作用。 LaunchDaemon 进程是匿名的,不能使用 AppKit。请参阅我上面的评论。
    【解决方案2】:

    使用IORegisterForSystemPower 不会提供您所寻找的事件。引用功能文档:

    /*! @function IORegisterForSystemPower

    @abstract 将调用者连接到 Root Power Domain IOService 用于接收系统的睡眠和唤醒通知。

    不提供系统关机和重启通知。

    【讨论】:

      猜你喜欢
      • 2018-01-08
      • 1970-01-01
      • 2015-11-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-11-18
      • 1970-01-01
      • 2018-10-26
      相关资源
      最近更新 更多