Демон, чтобы знать, когда пользователь входит в MAC

У меня работает демон (написанный на Obj C), и я хотел бы выполнить какое-либо действие, когда какой-либо пользователь входит в систему. Возможно ли, чтобы демон знал, когда конкретный пользователь входит в систему или выходит из нее в OSX? При входе в систему появляются какие-либо уведомления? Я хотел бы избежать использования элемента входа в систему или агента запуска. А также я хотел бы избежать опроса таймера для проверки вошедшего в систему пользователя.

1 ответ

Решение

Использование SCDynamicStoreCopyConsoleUser чтобы получить имя пользователя консоли.

CFStringRef  consoleUserName = nil;
uid_t        uid;
gid_t        gid;
consoleUserName = SCDynamicStoreCopyConsoleUser(NULL, &uid, &gid);

хранить consoleUserName в некоторой переменной-члене. Теперь создает сеанс для взаимодействия с динамическим хранилищем, поддерживаемым сервером конфигурации системы, используя SCDynamicStoreCreate

     SCDynamicStoreRef   store;
     CFStringRef         key;
     CFArrayRef          keys;
     CFRunLoopSourceRef  rls;
     store = SCDynamicStoreCreate(
                                     NULL, 
                                     CFSTR("com.apple.dts.ConsoleUser"), 
                                     callBackFunction, 
                                     NULL
                                     );

    // Set it up to notify us when the console user value changes.

    key = SCDynamicStoreKeyCreateConsoleUser(NULL);
    assert(key != NULL);

    keys = CFArrayCreate(NULL, (const void **) &key, 1, &kCFTypeArrayCallBacks);
    //assert(keys != NULL);

    success = SCDynamicStoreSetNotificationKeys(store, keys, NULL);
    //assert(success);

    // Add it to the runloop.

    rls = SCDynamicStoreCreateRunLoopSource(NULL, store, 0);
   // assert(rls != NULL);

    CFRunLoopAddSource(CFRunLoopGetCurrent(), rls, kCFRunLoopDefaultMode);


    mConsoleUserName = CopyCurrentConsoleUsername(store);
    CFRunLoopRun();

    CFRunLoopSourceInvalidate(rls);
    CFRelease(rls);
    CFRelease(keys);
    CFRelease(key);
    CFRelease(store);   

Воплощать в жизнь callBackFunction функция. Вы получите обратный вызов при изменении значения пользователя консоли.

static void callBackFunction(
                               SCDynamicStoreRef    store,
                               CFArrayRef          changedKeys,
                               void *              info
                               )
{
    CFStringRef         currentConsoleUser;
    Boolean             didChange;

    // Get the current console user.

    currentConsoleUser = CopyCurrentConsoleUsername(store);

    if (currentConsoleUser == NULL)
    {
        return;
    }
    didChange = ! CFEqual(storedvalue, currentConsoleUser);
    if (![currentConsoleUser isEqualToString:@"loginwindow"])
    {
      // pass this value to some method
    }
}
Другие вопросы по тегам