Программно уложить Mac в сон - PullRequest
8 голосов
/ 05 июня 2011

Я не могу найти никаких инструкций, как программно перевести Mac в спящий режим (в Objective-C). Я уверен, что это должна быть только одна строка, но не могли бы вы дать мне подсказку?

Ответы [ 6 ]

9 голосов
/ 05 июня 2011
#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 голосов
/ 06 июня 2011

Вы также можете использовать скриптовый мост.Код проекта:

SystemEventsApplication *systemEvents = [SBApplication applicationWithBundleIdentifier:@"com.apple.systemevents"];
[systemEvents sleep]; 
7 голосов
/ 17 апреля 2014

Том прав. Методы AE не работают, если дисплей спит. pmset sleepnow работает на 100%.

NSTask  *pmsetTask = [[NSTask alloc] init];
pmsetTask.launchPath = @"/usr/bin/pmset";
pmsetTask.arguments = @[@"sleepnow"];
[pmsetTask launch];
6 голосов
/ 05 июня 2011

Вы можете использовать AppleScript

NSAppleScript *script = [[NSAppleScript alloc] initWithSource:@"tell application \"System Events\" to sleep"];
NSDictionary *errorInfo;
[script executeAndReturnError:&errorInfo];
[script release];
1 голос
/ 20 февраля 2014

Я обнаружил, что запуск pmset sleepnow работал во время заставки, в то время как первые два ответа - нет.

0 голосов
/ 11 сентября 2018

На всякий случай, если кому-то интересно, как на самом деле работает pmset sleepnow, он использует IOPMSleepSystem API из раздела «Управление питанием» платформы IOKit. Вы можете проверить это, изучив исходный код pmset.c (ссылка из 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, что в итоге проверяет, присутствует ли вызывающий объект в массиве IOConsoleUsers в корневой записи IORegistry и, по-видимому, в данный момент зарегистрирован пользователь всегда присутствовать там.

...