我正在构建一个mac应用程序,在某个时候,需要将当前登录的用户切换到另一个预设用户。基本上是一个修改过的登录窗口。
有没有办法用cocoa做到这一点?
- Ari
修改:有没有办法不要求用户输入密码?
答案 0 :(得分:1)
正如在回答类似问题here中所解释的那样,在System文件夹中隐藏了一个名为“CGSession”的命令行工具,该工具应该可以满足您的需要。要在Cocoa应用程序中运行命令行工具,请查看NSTask。
要直接切换用户,请通过运行“id -u theUserName”找出预设用户的unix用户ID,然后使用输出作为执行参数:
/System/Library/CoreServices/Menu\ Extras/User.menu/Contents/Resources/CGSession -switchToUserID theUserIDNumber
或者只是到达登录窗口(不登出),运行:
/System/Library/CoreServices/Menu\ Extras/User.menu/Contents/Resources/CGSession -suspend
这是NSWorkspace的快速Obj-C类别。
NSWorkspace-SwitchUser.h:
#import <Cocoa/Cocoa.h>
@interface NSWorkspace (SwitchUser)
-(BOOL)switchToUser:(NSString *)userName;
@end
NSWorkspace-SwitchUser.m:
#import "NSWorkspace-SwitchUser.h"
#import <sys/types.h>
#import <pwd.h>
#import <stdlib.h>
#import <unistd.h>
#import <stdio.h>
@implementation NSWorkspace (SwitchUser)
-(BOOL)switchToUser:(NSString *)userName {
struct passwd *pwd = malloc(sizeof(struct passwd));
if (!pwd) {
NSLog(@"Couldn't allocate struct passwd for getpwnam_r.");
return FALSE;
}
size_t buf_len = sysconf(_SC_GETPW_R_SIZE_MAX) * sizeof(char);
char *buffer = malloc(buf_len);
if (!buffer) {
NSLog(@"Couldn't allocate buffer for getpwnam_r.");
return FALSE;
}
getpwnam_r([userName UTF8String], pwd, buffer, buf_len, &pwd);
if (!pwd) {
NSLog(@"getpwnam_r failed to find the requested user.");
return FALSE;
}
uid_t userID = pwd->pw_uid;
free(pwd);
free(buffer);
// Run CGSession with the -switchToUserID argument
NSTask *cgsTask = [NSTask launchedTaskWithLaunchPath:@"/System/Library/CoreServices/Menu Extras/User.menu/Contents/Resources/CGSession"
arguments:[NSArray arrayWithObjects:@"-switchToUserID",[NSString stringWithFormat:@"%u",userID],nil]];
// Wait till the task completes.
// Should be able to use -[NSTask waitUntilExit] instead, but it wasn't working for me :-P
while ([cgsTask isRunning]) {
usleep(100000);
}
return ([cgsTask terminationStatus] == 0);
}
@end
编辑:如果您需要切换用户而无需用户输入密码,那么在没有AppleScript的情况下似乎没有任何办法可以做到这一点,而AppleScript在任何意义上都不安全这个单词。但您可能会收集所需内容here和here。
答案 1 :(得分:1)
在我说出解决方案之前,我想说@ jrodatus的答案非常好,只是针对一个稍微不同的用例。
我想出了这个小苹果:
set theUser to "user"
set theUser to do shell script "/usr/bin/id -u " & theUser
set password to "pswd"
do shell script "/System/Library/CoreServices/Menu\\ Extras/User.menu/Contents/Resources/CGSession -switchToUserID " & theUser
repeat
try
tell application "System Events"
repeat until visible of process "SecurityAgent" is false
set visible of process "SecurityAgent" to false
end repeat
keystroke password
keystroke return
end tell
exit repeat
on error
tell application "System Events"
end tell
end try
end repeat
这只会触发登录屏幕,-switchToUserID
设置为用户名的用户ID。然后当至少有一个SecurityAgent
窗口(登录屏幕)可见时,模拟密码的击键,然后在运行登录窗口打开时输入结果,输入密码。此外,这没有延迟。