MacOS访问性权限来监听鼠标/键盘事件

 方法一、 使用CGEventPost(kCGHIDEventTap, push);获取辅助功能权限

    CGEventSourceRef source = CGEventSourceCreate(kCGEventSourceStatePrivate);
    CGEventRef push = CGEventCreateKeyboardEvent(source, 1, 0);
    CGEventSetSource(push, source);
    CGEventSetFlags(push, NULL);
    CGEventPost(kCGHIDEventTap, push);
    CFRelease(push);
    CFRelease(source);

注意:Intel 架构没问题,终端输入

tccutil reset Accessibility com.niu.xxx
Successfully reset Accessibility approval status for com.niu.xxx

虽然m1 架构,也提示

tccutil reset Accessibility com.niu.xxx
Successfully reset Accessibility approval status for com.niu.xxx

但辅助功能里面,仍存在该app

方法二、使用AXIsProcessTrustedWithOptions(); 获取辅助功能权限

AppDelegate.m

#import "AppDelegate.h"
BOOL checkAccessibility(void)
{
   // NSString *urlString = @"x-apple.systempreferences:com.apple.preference.security?Privacy_Accessibility";
   // [[NSWorkspace sharedWorkspace] openURL:[NSURL URLWithString:urlString]];
    /*
    NSDictionary* opts = @{(__bridge id)kAXTrustedCheckOptionPrompt: @YES};
    return AXIsProcessTrustedWithOptions((__bridge CFDictionaryRef)opts);
     */
    const void * keys[] = { kAXTrustedCheckOptionPrompt };
    const void * values[] = { kCFBooleanTrue };
    CFDictionaryRef options = CFDictionaryCreate(
            kCFAllocatorDefault,
            keys,
            values,
            sizeof(keys) / sizeof(*keys),
            &kCFCopyStringDictionaryKeyCallBacks,
            &kCFTypeDictionaryValueCallBacks);

    return AXIsProcessTrustedWithOptions(options);

}
@interface AppDelegate ()
@property NSTimer* timer;
@end

@implementation AppDelegate

- (void)applicationDidFinishLaunching:(NSNotification *)aNotification {
    // Insert code here to initialize your application
    if (!checkAccessibility()) {
      self.timer = [NSTimer scheduledTimerWithTimeInterval:3.0
                                                   repeats:YES
                                                     block:^(NSTimer* timer) {
                                                       [self relaunchIfProcessTrusted];
                                                     }];
    }else{
        NSLog(@"registering keydown mask");
        [NSEvent addGlobalMonitorForEventsMatchingMask:NSEventMaskKeyDown
                                               handler:^(NSEvent *event){
                                                   NSLog(@"keydown: %@", event.characters);

                                               }];
    }
    
}
- (void)relaunchIfProcessTrusted {
  if (AXIsProcessTrusted()) {
      if(self.timer){
         
          NSLog(@"registering keydown mask");
          [NSEvent addGlobalMonitorForEventsMatchingMask:NSEventMaskKeyDown
                                                 handler:^(NSEvent *event){
                                                     NSLog(@"keydown: %@", event.characters);

                                                 }];
          [self.timer invalidate];
          self.timer = nil;
      }
      /*
      这段代码是使用 Objective-C 中的 NSTask 类创建一个新的进程。具体来说,它启动了一个与当前应用程序不共享内存空间的可执行文件,并且没有指定额外的参数。

      其中,NSTask 类是 Cocoa 框架中的一个类,用于启动新进程、执行命令和处理输出等操作。launchedTaskWithLaunchPath:arguments: 是 NSTask 类中的一个类方法,它接受两个参数:路径和参数。其中,launchPath 参数指定要启动的可执行文件的路径,而 arguments 参数是一个字符串数组,用于传递给可执行文件的参数列表。在这个例子中,参数列表为空数组。

      而 [[NSBundle mainBundle] executablePath] 是一个 NSBundle 类的实例方法,用于获取当前应用程序的主要可执行文件的路径。这个路径在每个应用程序中都是唯一的,可以用于查找和执行其他资源。在这个例子中,它作为启动的可执行文件的路径。
       */
//    [NSTask launchedTaskWithLaunchPath:[[NSBundle mainBundle] executablePath] arguments:@[]];
//    [NSApp terminate:nil];//作用是终止当前正在运行的 macOS 应用程序
  }else{
     
  }
}
@end

这种方法想要生效,必须禁用沙盒功能,需要将App Sandbox 设置成 NO

注意:

1. Mac App Store 中的应用无法获得辅助功能权限

2. Apple 沙盒应用程序不能具有该级别的控制(即完全的鼠标/窗口控制)

你可能感兴趣的:(MacOS,github)