objective-c – 全球活动,Mac App Store和沙盒

objective-c – 全球活动,Mac App Store和沙盒,第1张

概述我正在开发一个应用程序,其中使用全局按键事件将是其 *** 作的必要条件.此外,我计划通过App Store严格分发. (它是一个Mac应用程序,而不是iOS.)我已经得到了一个通过addGlobalMonitorForEventsMatchingMask监听全局事件的示例,但有一些警告. 注意:我正在选择使用现代API而不依赖于早期的Carbon热键方法.如果他们最终被弃用,我不想在以后解决这个问题. 我正在开发一个应用程序,其中使用全局按键事件将是其 *** 作的必要条件.此外,我计划通过App Store严格分发. (它是一个Mac应用程序,而不是iOS.)我已经得到了一个通过addGlobalMonitorForEventsMatchingMask监听全局事件的示例,但有一些警告.

注意:我正在选择使用现代API而不依赖于早期的Carbon热键方法.如果他们最终被弃用,我不想在以后解决这个问题.

主要问题是必须信任应用程序才能检测到全局事件.否则,必须为所有应用启用辅助功能.启用辅助功能时,会成功检测到事件.此要求记录在此处,http://developer.apple.com/library/mac/#DOCUMENTATION/Cocoa/Conceptual/EventOverview/MonitoringEvents/MonitoringEvents.html.

我希望对我的用户而言,他们不必启用辅助功能.从我已经完成的其他研究中,您可以通过调用AXMakeProcesstrusted来获取可信任的应用程序,然后重新启动应用程序.

在我正在使用的代码中,我没有得到身份验证提示.应用程序将重新启动,但仍然不受信任(可能是因为我没有收到身份验证提示).这是我这部分的代码:

- (voID)applicationDIDFinishLaunching:(NSNotification *)aNotification{    if (!AXAPIEnabled() && !AXIsProcesstrusted()) {        Nsstring *appPath = [[NSBundle mainBundle] bundlePath];        AXError error = AXMakeProcesstrusted( (CFStringRef)CFBrIDgingRetain(appPath) );        [self restartApp];    }}- (voID)restartApp{    NSTask *task = [[NSTask alloc] init];    NSMutableArray *args = [NSMutableArray array];    [args addobject:@"-c"];    [args addobject:[Nsstring stringWithFormat:@"sleep %d; open \"%@\"",3,[[NSBundle mainBundle] bundlePath]]];    [task setLaunchPath:@"/bin/sh"];    [task setArguments:args];    [task launch];    [NSApp terminate:nil];}

此外,我在https://developer.apple.com/library/mac/#documentation/security/conceptual/authorization_concepts/03authtasks/authtasks.html#//apple_ref/doc/uid/TP30000995-CH206-BCIGAIAG查看了授权服务任务的文档.

d出的第一件事就是d出这个信息框,“重要的是,应用程序沙箱中不支持授权服务API,因为它允许权限提升.”

如果在重新启动应用程序之前需要此API来获取身份验证提示,则似乎在未启用辅助功能的情况下我可能无法获取全局事件.

总之,我的具体问题是:

>我的示例代码中是否有关于如何获取的错误
身份验证提示出现?
>为了显示身份验证提示,我是必需的
使用Authorization Services API?
>是否有可能或不可能拥有一个沙盒应用程序
访问全球事件?

解决方法 首先,您无法自动允许应用程序使用可在沙盒环境中工作的辅助功能API,从而可以在应用商店中使用.推荐的方法是简单地引导用户,以便他们自己轻松启用它.新的API调用AXIsProcesstrusteDWithOptions正是为此:

NSDictionary *options = @{(ID) kAXTrustedCheckOptionPrompt : @YES};        AXIsProcesstrusteDWithOptions((CFDictionaryRef) options);

现在,到你的第一个和第二个问题(仅仅是为了完整性 – 再次它在沙箱中不起作用):
AXMakeProcesstrusted背后的想法是,您实际上创建了一个新的auxiliary application,您从主应用程序以root身份运行.然后,该实用程序调用AXMakeProcesstrusted传递主应用程序的可执行文件.最后,您必须重新启动主应用程序. OSX 10.9中已弃用API调用.

要以root身份生成新进程,必须使用带有SMJobsubmit的launchd.这将提示用户提供身份验证提示,说明应用程序正在尝试安装帮助程序工具以及是否应该允许它.具体来说:

+ (BOol)makeTrusteDWithError:(NSError **)error {        Nsstring *label = FMTStr(@"%@.%@",kShiftItAppBundleID,@"mktrusted");        Nsstring *command = [[NSBundle mainBundle] pathForAuxiliaryExecutable:@"mktrusted"];        AuthorizationItem authItem = {kSMRightmodifySystemDaemons,NulL,0};        AuthorizationRights authRights = {1,&authItem};        AuthorizationFlags flags = kAuthorizationFlagInteractionAllowed | kAuthorizationFlagPreAuthorize | kAuthorizationFlagExtendRights;        AuthorizationRef auth;        if (AuthorizationCreate(&authRights,kAuthorizationEmptyEnvironment,flags,&auth) == errAuthorizationSuccess) {           // this is actually important - if from any reason the job was not removed,it won't @R_813_4404@           // to check for the running jobs use: sudo launchctl List           // the sudo is important since this job runs under root           SMJobRemove(kSMDomainSystemlaunchd,(CFStringRef) label,auth,false,NulL);           // this is actually the launchd pList for a new process           // https://developer.apple.com/library/mac/documentation/Darwin/Reference/Manpages/man5/launchd.pList.5.HTML#//apple_ref/doc/man/5/launchd.pList           NSDictionary *pList = @{                   @"Label" : label,@"RunAtLoad" : @YES,@"ProgramArguments" : @[command],@"DeBUG" : @YES           };           BOol ret;           if (SMJobsubmit(kSMDomainSystemlaunchd,(CFDictionaryRef) pList,(CFErrorRef *) error)) {               FMTLogDeBUG(@"Executed %@",command);               ret = YES;           } else {               FMTLogError(@"Failed to execute %@ as priviledged process: %@",command,*error);               ret = NO;           }           // From whatever reason this dID not work very well           // seems like it removed the job before it was executed           // SMJobRemove(kSMDomainSystemlaunchd,NulL);           AuthorizationFree(auth,0);           return ret;        } else {           FMTLogError(@"Unable to create authorization object");           return NO;        }    }

至于重新启动,通常还使用外部实用程序来完成,等待主应用程序完成并再次启动它(通过使用PID).如果您使用sparkle framework,则可以重复使用现有的:

+ (voID) @R_813_4404@ {         Nsstring *@R_813_4404@ = [[NSBundle bundleForClass:[SUUpdater class]] pathForResource:@"@R_813_4404@" ofType:@""];         Nsstring *path = [[NSBundle mainBundle] bundlePath];         Nsstring *pID = FMTStr(@"%d",[[nsprocessInfo processInfo] processIDentifIEr]);         [NSTask launchedTaskWithLaunchPath:@R_813_4404@ arguments:@[path,pID]];         [NSApp terminate:self];    }

另一种选择是破解/ library / Application Support / com.apple.TCC / TCC.db sqlite数据库使用辅助助手手动添加权限:

Nsstring *sqlite = @"/usr/bin/sqlite3";    Nsstring *sql = FMTStr(@"INSERT or REPLACE INTO access values ('kTCCServiceAccessibility','%@',1,NulL);",MY_BUNDLE_ID);     NSArray *args = @[@"/library/Application Support/com.apple.TCC/TCC.db",sql];    NSTask *task = [NSTask launchedTaskWithLaunchPath:sqlite arguments:args];    [task waitUntilExit];

然而,这将使应用程序无法成为应用商店.更重要的是它只是一个黑客攻击,db / schema可以随时更改.一些应用程序(例如divvy.app用于执行此 *** 作)在应用程序安装程序安装后脚本中使用此Hack.这种方式可以防止对话框告知应用程序正在请求安装辅助工具.

总结

以上是内存溢出为你收集整理的objective-c – 全球活动,Mac App Store和沙盒全部内容,希望文章能够帮你解决objective-c – 全球活动,Mac App Store和沙盒所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/web/1032976.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-24
下一篇 2022-05-24

发表评论

登录后才能评论

评论列表(0条)

保存