Mec*_*cki 21
它没有正式记录并使用私有API,但以下适用于MacOS 10.10(也可能在早期系统上):
// lockscreen.c
extern int SACLockScreenImmediate ( void );
int main ( ) {
return SACLockScreenImmediate();
}
Run Code Online (Sandbox Code Playgroud)
建立:
clang -F /System/Library/PrivateFrameworks -framework login -o lockscreen lockscreen.c
Run Code Online (Sandbox Code Playgroud)
现在调用./lockscreen将立即锁定屏幕,无论用户在其安全首选项中配置了什么(是否锁定屏幕保护程序/系统睡眠)并且不将用户注销.这是系统内部用于锁定屏幕的功能.
我强烈反对使用它,它可能会破坏你的应用程序,我甚至不确定我是否正确调用它(可能它需要参数,也许它有一个返回值),所以它甚至可能会打破你的整个系统(暂时 - 重启将会修理一切),谁知道.我只是想在某处发布文档.
如果有比我更好的黑客技能的人可以再分析一下这个电话,这将是很好的和有用的.
小智 9
要锁定屏幕,请致电:
/ System/Library/CoreServices/Menu\Extras/User.menu/Contents/Resources/CGSession -suspend
如果你真的想做钥匙串做的事情(即只是锁定屏幕,不要去登录窗口),这很容易:
io_registry_entry_t r = IORegistryEntryFromPath(kIOMasterPortDefault, "IOService:/IOResources/IODisplayWrangler");
if (r) {
IORegistryEntrySetCFProperty(r, CFSTR("IORequestIdle"), sleep ? kCFBooleanTrue);
IOObjectRelease(r);
}
Run Code Online (Sandbox Code Playgroud)
但是,这仅在用户将"睡眠后需要密码或屏幕保护程序开始"设置为"立即"时才有效.但是,您可以立即将它设置为它们,然后将其设置为完成后的状态.事实证明,生效可能相当棘手(请参阅此答案以获取更多信息),但可以完成.把它们放在一起,你有类似的东西:
- (void)lockScreen;
{
int screenSaverDelayUserSetting = 0;
screenSaverDelayUserSetting = [self readScreensaveDelay];
if (screenSaverDelayUserSetting != 0) {
// if the delay isn't already 0, temporarily set it to 0 so the screen locks immediately.
[self setScreensaverDelay:0];
[self touchSecurityPreferences];
}
io_registry_entry_t r = IORegistryEntryFromPath(kIOMasterPortDefault, "IOService:/IOResources/IODisplayWrangler");
if (r) {
IORegistryEntrySetCFProperty(r, CFSTR("IORequestIdle"), sleep ? kCFBooleanTrue : kCFBooleanFalse);
IOObjectRelease(r);
}
if (screenSaverDelayUserSetting != 0) {
[self setScreensaverDelay:screenSaverDelayUserSetting];
[self launchAndQuitSecurityPreferences];
}
}
- (void)touchSecurityPreferences;
{
// necessary for screen saver setting changes to take effect on file-vault-enabled systems
// NOTE: this *only* works when going from non-zero settings of askForPasswordDelay to zero.
NSAppleScript *kickSecurityPreferencesScript = [[[NSAppleScript alloc] initWithSource: @"tell application \"System Events\" to tell security preferences to set require password to wake to true"] autorelease];
[kickSecurityPreferencesScript executeAndReturnError:nil];
}
- (void)launchAndQuitSecurityPreferences;
{
// necessary for screen saver setting changes to take effect on file-vault-enabled systems when going from a askForPasswordDelay setting of zero to a non-zero setting
NSAppleScript *kickSecurityPreferencesScript = [[[NSAppleScript alloc] initWithSource:
@"tell application \"System Preferences\"\n"
@" tell anchor \"General\" of pane \"com.apple.preference.security\" to reveal\n"
@" activate\n"
@"end tell\n"
@"delay 0\n"
@"tell application \"System Preferences\" to quit"] autorelease];
[kickSecurityPreferencesScript executeAndReturnError:nil];
}
- (int)readScreensaveDelay;
{
NSArray *arguments = @[@"read",@"com.apple.screensaver",@"askForPasswordDelay"];
NSTask *readDelayTask = [[[NSTask alloc] init] autorelease];
[readDelayTask setArguments:arguments];
[readDelayTask setLaunchPath: @"/usr/bin/defaults"];
NSPipe *pipe = [NSPipe pipe];
[readDelayTask setStandardOutput:pipe];
NSFileHandle *file = [pipe fileHandleForReading];
[readDelayTask launch];
NSData *resultData = [file readDataToEndOfFile];
NSString *resultString = [[NSString alloc] initWithData:resultData encoding:NSUTF8StringEncoding];
return resultString.intValue;
}
- (void)setScreensaverDelay:(int)delay;
{
NSArray *arguments = @[@"write",@"com.apple.screensaver",@"askForPasswordDelay", [NSString stringWithFormat:@"%i", delay]];
NSTask *resetDelayTask = [[[NSTask alloc] init] autorelease];
[resetDelayTask setArguments:arguments];
[resetDelayTask setLaunchPath: @"/usr/bin/defaults"];
[resetDelayTask launch];
}
Run Code Online (Sandbox Code Playgroud)
使用swift做Mecki的答案:
let libHandle = dlopen("/System/Library/PrivateFrameworks/login.framework/Versions/Current/login", RTLD_LAZY)
let sym = dlsym(libHandle, "SACLockScreenImmediate")
typealias myFunction = @convention(c) Void -> Void
let SACLockScreenImmediate = unsafeBitCast(sym, myFunction.self)
SACLockScreenImmediate()
Run Code Online (Sandbox Code Playgroud)
在这里:https: //github.com/ftiff/MenuLock/blob/master/MenuLock/AppDelegate.swift#L126
我没有看到任何这样的记录,但菜单使用 ScreenSaver 框架,它定义了这一点:
@interface ScreenSaverDefaults : NSUserDefaults
{
@private
NSMutableDictionary *_defaults;
NSMutableDictionary *_registeredDefaults;
NSString *_userName;
NSString *_domainName;
BOOL _dirty;
BOOL _screenLockPrefChanged;
}
+ (id) defaultsForModuleWithName:(NSString *)inModuleName;
@end
Run Code Online (Sandbox Code Playgroud)