【问题标题】:Execute command just before Mac going to sleep在 Mac 进入睡眠状态之前执行命令
【发布时间】:2012-11-12 02:51:00
【问题描述】:

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

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

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

问题:有什么方法可以知道我的 Mac 何时准备睡觉?我可以让我的程序收听一些中断吗?

【问题讨论】:

    标签: c macos sleep


    【解决方案1】:

    您可以使用 I/O Kit 来实现,查看 Apple 的 QA1340: Registering and unregistering for sleep and wake notifications。您可能还想 分析SleepWatcher 实用程序源或根据您的需要使用/集成。 从主页:

    SleepWatcher 2.2(运行 Mac OS X 10.5 到 10.8,包括源代码) 是一个用于 Mac OS X 的命令行工具(守护进程),用于监控睡眠、唤醒和 Mac的闲置。它可用于在 Mac 或 Mac 的显示器在给定时间后进入睡眠模式或唤醒 没有用户交互或当用户在休息后恢复活动时 连接或拆卸 Mac 笔记本电脑的电源时。它还可以 使 Mac 进入睡眠模式或检索自上次用户活动以来的时间。一种 需要对 Unix 命令行有一点了解才能从中受益 这个软件。

    【讨论】:

      【解决方案2】:

      我附在我的 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);
      }
      

      【讨论】:

        猜你喜欢
        • 2021-06-16
        • 1970-01-01
        • 2011-09-08
        • 2018-01-30
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-07-14
        • 1970-01-01
        相关资源
        最近更新 更多