-->

Objective-C的脚本桥接和苹果远程桌面(Objective-C Scripting Brid

2019-09-28 18:19发布

尝试自动通过脚本桥接使用Objective-C查看苹果远程桌面的计算机与此:


    @try {
        SBApplication *RD = [SBApplication applicationWithBundleIdentifier:@"com.apple.RemoteDesktop"];

        // (code to check for ARD running and installed omitted here)
        [RD activate]; // works just fine

        RemoteDesktopComputer *computer = [[[RD classForScriptingClass:@"computer"] alloc]     initWithProperties:
            [NSDictionary dictionaryWithObjectsAndKeys:
                ipAddress,@"InternetAddress", // looked up from header
                nil
             ]
        ];

        // attempt to add it to a container first:
        [(SBElementArray*)[(RemoteDesktopApplication*)RD computers] addObject:computer]; 
        // this is what raises the exception:
        [computer observeZooming:Nil];
    }
    @catch (NSException *e) {
        NSLog(@"Exception: %@", [e description]);
    }

运行此债收益率在日志中以下情况除外:

    Exception: *** -[SBProxyByClass observeZooming:]: object has not been added to a container yet; selector not recognized [self = 0x6050004819b3]

我已经做了尽可能多的研究,有关于该主题,并了解到,SB是不是最容易处理,因为它是如何在引擎盖下与有线,但任何专家或本地脚本桥的老兵(无第三方框架或大于OBJ-C等语言,请)是大加赞赏。

像链接到ScriptingBridge.framework和导入远程Desktop.h执行所有先决条件 - 的类型转换是为了避免出现什么建筑时是不可避免的链接时错误...

编辑1:阅读SBObject文档(RemoteDesktopComputer的父母)说,这是一个参考,而不是一个实际的例子,你可以通过调用SBObject的get方法(返回ID)获取。 所以,我想运行此也无奈接受了相同的结果:

    [[computer get] observeZooming:Nil];

下面是关于SBObject的文档: https://developer.apple.com/library/mac/documentation/cocoa/Reference/SBObject_Class/SBObject/SBObject.html#//apple_ref/occ/instm/SBObject/get

仍在尝试...

Answer 1:

(FWIW,我已经有了下面的如何写了,所以我在这里留下供日后参考。)


如何使用AppleScript的ObjC到位脚本大桥

脚本大桥,充其量一个80/20/80“解决方案”(即80的它的工作原理%的时间,它的失败,20%的时间,而80%的时间你不知道为什么)。 有小点,试图用SB争论时,它打破的东西,在AppleScript的工作得很好 - 负责苹果的工程师设计的,它是故意的方式,简单地拒绝接受他们打破了规范[1]和搞砸了。 其结果是,在AppleScript语言写的,其所有其他的不足,仍然是保证正确地说苹果事件的唯一支持的解决方案[2]。

幸运的是,因为OS X 10.6也已经提供另一种选择:使用ObjC你所有的通用编程的东西,只有通过AppleScript的ObjC桥为IPC东西调入的AppleScript。

从您的ObjC代码POV,您的基于AppleScript的ASOC“类”是从正规ObjC类的更多或更少的区别。 这需要一点点摆弄成立的,并且过桥时,你会支付通行的一点,但考虑到替代品的残废的,不可靠的性质,它的任何东西不平凡支持的选项是最可怕的。

假设你已经有一个现有的基于ObjC项目,这里是如何在基于ASOC类添加到它:

  1. 在目标> APPNAME>构建阶段>链接二进制与图书馆,添加AppleScriptObjC.framework

  2. 在支持文件> main.m ,添加导入与负载线如图所示:

     #import <Cocoa/Cocoa.h> #import <AppleScriptObjC/AppleScriptObjC.h> int main(int argc, const char * argv[]) { [[NSBundle mainBundle] loadAppleScriptObjectiveCScripts]; return NSApplicationMain(argc, argv); } 
  3. 要定义一个名为基于ASOC类MyStuff这是从ObjC调用,创建一个MyStuff.h声明它的公共方法接口文件:

     // MyStuff.h #import <Cocoa/Cocoa.h> @interface MyStuff : NSObject // (note: C primitives are only automatically bridged when calling from AS into ObjC; // AS-based methods with boolean/integer/real parameters or results use NSNumber*) -(NSNumber *)square:(NSNumber *)aNumber; @end 

    连同MyStuff.applescript包含它的实现文件:

     -- MyStuff.applescript script MyStuff property parent : class "NSObject" on square_(aNumber) return aNumber ^ 2 end square_ end script 
  4. 由于MyStuff类没有一个ObjC实现,链接器无法将ObjC代码在编译时链接到它。 相反,使用NSClassFromString()来查找类对象在运行时:

     #import "MyClass.h" ... MyStuff *stuff = [[NSClassFromString(@"MyStuff") alloc] init]; 

    否则,它几乎是在正常使用原生ObjC类区分:

     NSNumber *result = [stuff square: @3]; NSLog(@"Result: %@", result); 

HTH

-

[1]苹果管理打破了原有的AppleScript队首次发布后不久,导致其设计师为响应退出,所以很多这方面的东西恰恰应该如何工作的知识的丢失。 具体而言,一个完整的,正式的规范从未被生产为应用开发者设计他们的脚本支持时要遵循的,所以他们现在能做的是利用个人的判断和最佳猜测,然后测试针对的AppleScript检查它当过希望。 因此,AppleScript的自己的苹果事件桥是每一个脚本化的应用在过去的20年来实现对事实上的规范 ,这样其他AE桥都不能正常工作的唯一方法是,如果他们模仿AS自己桥层层分解,最后查询和怪癖-一个教训,遗憾的是,作为球队目前已经多次未能理解[2]。

[2]的JavaScript支持自动化的苹果事件同样糟糕和捣毁,顺便说一句。



Answer 2:

脚本桥接是有缺陷的,模糊的一塌糊涂,所以,当一个应用程序的命令无法工作你不知道,如果问题是SB有缺陷或应用程序本身是马车或只是需要你那句它以不同的方式。

因此,第一步是写在AS测试脚本,看看它在那里工作。 如果是这样,这是SB这是废话; 如果没有,请尝试使用AS代码摆弄(如尝试措辞为基准at以不同的方式的参数,或者完全忽略它),直到它。

你也应该问苹果的AppleScript的用户和ARD邮件列表和其他任何地方,ARD脚本编写者很可能会挂出,因为大多数的应用程序的脚本文件是严重不足,所以很多如何做事的知识是口碑。 (你真的想谈谈这家伙是约翰·C·韦尔奇,又名@bynkii ,因为他是ARD脚本的大师。)



文章来源: Objective-C Scripting Bridge and Apple Remote Desktop