在 Mac 进入睡眠状态之前执行命令

14

我编写了一个C程序/LaunchDaemon,用于检查我的MacBook是否在家中(连接到我的WLAN)。如果是,则禁用密码保护;否则启用密码保护。

很简单。但问题是,当我带着我的MacBook去其他地方并且禁用了密码保护时,它将在没有密码保护的情况下唤醒。

我对此的解决方法是:每次在MacBook进入睡眠状态之前,只需启用密码保护。

问题:有没有办法找出我的Mac正在准备进入睡眠状态?有一些中断可以让我的程序监听吗?

2个回答

8
你可以使用I/O Kit来完成,参考苹果公司的QA1340:注册和注销睡眠和唤醒通知。你可能还想分析SleepWatcher实用程序源代码或根据需要使用/集成。从主页开始:
SleepWatcher 2.2(适用于Mac OS X 10.5至10.8,包括源代码)是Mac OS X的命令行工具(守护程序),用于监视Mac的睡眠、唤醒和空闲状态。当Mac或Mac显示器进入睡眠模式或唤醒后,经过一段时间没有用户交互或用户在休息后恢复活动时,它可以用于执行Unix命令,或当Mac笔记本电脑的电源连接或断开时。它还可以将Mac置于睡眠模式或检索自上次用户活动以来的时间。需要一些Unix命令行的知识才能从此软件中受益。

3

我在下面附上了我的C文件beforesleep.c的内容,它执行一些命令行命令(在我的情况下是shell命令和AppleScript脚本),当接收到“将要休眠”通知时。

你可以放置你的代码的地方:

为了在Mac即将进入睡眠状态时运行您的代码,只需用您希望运行的代码替换system(...)调用即可。

在我的情况下,我使用system(),因为它允许我运行作为字符串传递的shell命令,但是如果您喜欢只运行C代码,则可以将您的C代码放在那里。

如何构建它

为了构建这个文件,我运行:

gcc -framework IOKit -framework Cocoa beforesleep.c

备注

如果您要使用此代码,请确保它始终在后台运行。例如,我有一个Cron作业,确保此代码始终运行,并在任何原因下意外终止时重新启动它(尽管到目前为止从未发生过)。如果您足够有经验,可以找到更聪明的方法来确保这一点。

更多信息

有关此操作的更多详细信息,请参见this link(已由sidyll建议)。

代码模板

#include <ctype.h>
#include <stdlib.h>
#include <stdio.h>
 
#include <mach/mach_port.h>
#include <mach/mach_interface.h>
#include <mach/mach_init.h>
 
#include <IOKit/pwr_mgt/IOPMLib.h>
#include <IOKit/IOMessage.h>
 
io_connect_t  root_port; // a reference to the Root Power Domain IOService
 
void
MySleepCallBack( void * refCon, io_service_t service, natural_t messageType, void * messageArgument )
{
    switch ( messageType )
    {
 
        
        case kIOMessageCanSystemSleep:
            IOAllowPowerChange( root_port, (long)messageArgument );
            break;
 
        case kIOMessageSystemWillSleep:
            system("/Users/andrea/bin/mylogger.sh");
            system("osascript /Users/andrea/bin/pause_clockwork.scpt");
 
            IOAllowPowerChange( root_port, (long)messageArgument );
            break;
 
        case kIOMessageSystemWillPowerOn:
            //System has started the wake up process...
            break;
 
        case kIOMessageSystemHasPoweredOn:
            //System has finished waking up...
        break;
 
        default:
            break;
 
    }
}
 
 
int main( int argc, char **argv )
{
    
    // notification port allocated by IORegisterForSystemPower
    IONotificationPortRef  notifyPortRef;
 
    // notifier object, used to deregister later
    io_object_t            notifierObject;
   // this parameter is passed to the callback
    void*                  refCon;
 
    // register to receive system sleep notifications
 
    root_port = IORegisterForSystemPower( refCon, &notifyPortRef, MySleepCallBack, &notifierObject );
    if ( root_port == 0 )
    {
        printf("IORegisterForSystemPower failed\n");
        return 1;
    }
 
    // add the notification port to the application runloop
    CFRunLoopAddSource( CFRunLoopGetCurrent(),
            IONotificationPortGetRunLoopSource(notifyPortRef), kCFRunLoopCommonModes );
 
    /* Start the run loop to receive sleep notifications. Don't call CFRunLoopRun if this code
        is running on the main thread of a Cocoa or Carbon application. Cocoa and Carbon
        manage the main thread's run loop for you as part of their event handling
        mechanisms.
    */
    CFRunLoopRun();
 
    //Not reached, CFRunLoopRun doesn't return in this case.
    return (0);
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接