以编程方式让Mac进入睡眠状态

问题描述 投票:8回答:6

我找不到任何有关如何将Mac以编程方式置于睡眠模式的指令(在Objective-C中)。我敢肯定它应该只有一行,但你可以给我一个提示吗?

objective-c cocoa macos sleep
6个回答
9
投票
#include <stdio.h> 
#include <CoreServices/CoreServices.h>
#include <Carbon/Carbon.h>

SendAppleEventToSystemProcess(kAESleep);

OSStatus SendAppleEventToSystemProcess(AEEventID EventToSend)
{
    AEAddressDesc targetDesc;
    static const ProcessSerialNumber kPSNOfSystemProcess = { 0, kSystemProcess };
    AppleEvent eventReply = {typeNull, NULL};
    AppleEvent appleEventToSend = {typeNull, NULL};

    OSStatus error = noErr;

    error = AECreateDesc(typeProcessSerialNumber, &kPSNOfSystemProcess, 
                                            sizeof(kPSNOfSystemProcess), &targetDesc);

    if (error != noErr)
    {
        return(error);
    }

    error = AECreateAppleEvent(kCoreEventClass, EventToSend, &targetDesc, 
                   kAutoGenerateReturnID, kAnyTransactionID, &appleEventToSend);

    AEDisposeDesc(&targetDesc);
    if (error != noErr)
    {
        return(error);
    }

    error = AESend(&appleEventToSend, &eventReply, kAENoReply, 
                  kAENormalPriority, kAEDefaultTimeout, NULL, NULL);

    AEDisposeDesc(&appleEventToSend);
    if (error != noErr)
    {
        return(error);
    }

    AEDisposeDesc(&eventReply);

    return(error); 
}

关于https://developer.apple.com/library/content/qa/qa1134/_index.html的更多细节


8
投票

您还可以使用脚本桥。草案代码是

SystemEventsApplication *systemEvents = [SBApplication applicationWithBundleIdentifier:@"com.apple.systemevents"];
[systemEvents sleep]; 

7
投票

汤姆是对的。如果显示器处于休眠状态,AE方法将失败。 pmset sleepnow 100%工作。

NSTask  *pmsetTask = [[NSTask alloc] init];
pmsetTask.launchPath = @"/usr/bin/pmset";
pmsetTask.arguments = @[@"sleepnow"];
[pmsetTask launch];

6
投票

您可以使用AppleScript

NSAppleScript *script = [[NSAppleScript alloc] initWithSource:@"tell application \"System Events\" to sleep"];
NSDictionary *errorInfo;
[script executeAndReturnError:&errorInfo];
[script release];

1
投票

我发现运行pmset sleepnow在屏幕保护程序中工作,而前两个答案没有。


0
投票

如果有人好奇pmset sleepnow实际上是如何工作的 - 它使用来自IOKit框架的电源管理部分的IOPMSleepSystem API。您可以通过检查pmset.c source code(来自macOS 10.13.3的链接)来检查这一点。

因此,您可以通过以下代码段来请求睡眠,而不是调用pmset

#include <IOKit/pwr_mgt/IOPMLib.h>

void SleepNow()
{
    io_connect_t fb = IOPMFindPowerManagement(MACH_PORT_NULL);
    if (fb != MACH_PORT_NULL)
    {
        IOPMSleepSystem(fb);
        IOServiceClose(fb);
    }
}

不要被调用者吓到必须是root或控制台用户注释文档,因为它似乎适用于任何标准登录用户。

通过遵循源代码,看起来它使用IOUserClient::clientHasPrivilege调用kIOClientPrivilegeLocalUser,最终检查调用者是否存在于根IORegistry条目中的IOConsoleUsers数组中,并且显然当前登录的用户始终存在于那里。

© www.soinside.com 2019 - 2024. All rights reserved.