Objective-C 脚本桥和 Apple 远程桌面 [英] Objective-C Scripting Bridge and Apple Remote Desktop

查看:26
本文介绍了Objective-C 脚本桥和 Apple 远程桌面的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

尝试通过 Objective-C 中的脚本桥自动查看 Apple 远程桌面中的计算机:

Trying to automatically view a computer in Apple Remote Desktop via Scripting Bridge in Objective-C with this:


    @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]);
    }

运行这个会在日志中产生以下异常:

Running this yields the following exception in the log:

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

我已经做了尽可能多的关于这个主题的研究,并且了解到 SB 并不是最容易处理的,因为它是如何在引擎盖下连接的,但是本地 Scripting Bridge 的任何专家或老手(没有非常感谢 obj-c 以外的第三方框架或语言).

I've done as much research as there is available on this subject and have learned that SB isn't the easiest to deal with because of how it's wired under the hood, but any experts or veterans of native Scripting Bridge (no third party frameworks or languages other than obj-c, please) is much appreciated.

执行所有先决条件,例如链接到 ScriptingBridge.framework 和导入 Remote Desktop.h - 类型转换是为了避免构建时似乎不可避免的链接时错误...

All prerequisites like linking to the ScriptingBridge.framework and importing Remote Desktop.h are performed - the typecasts are to avoid what appear to be unavoidable link-time errors when building...

编辑 1: 阅读有关 SBObject(RemoteDesktopComputer 的父级)的文档说它是一个引用而不是一个实际实例,您可以通过调用 SBObject 的 get 方法(返回 id)获取它.所以我也尝试运行它,但不幸的是收到了相同的结果:

Edit 1: Reading the documentation on SBObject (parent of RemoteDesktopComputer) says that it's a reference rather than an actual instance, which you can fetch by calling SBObject's get method (returns id). So I tried running this as well but unfortunately received the same results:

    [[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

Here's the documentation on SBObject: https://developer.apple.com/library/mac/documentation/cocoa/Reference/SBObject_Class/SBObject/SBObject.html#//apple_ref/occ/instm/SBObject/get

还在努力中...

推荐答案

(FWIW,我已经写了下面的 How To,所以我把它留在这里以备将来参考.)

(FWIW, I already had the following How To written up, so I'm leaving it here for future reference.)

Scripting Bridge 充其量是一个 80/20/80 的解决方案"(即 80% 的时间有效,20% 的时间失败,而 80% 的时间您不知道为什么).当 SB 破坏了在 AppleScript 中运行良好的东西时,试图与 SB 争论是没有意义的——负责的 Apple 工程师故意这样设计它,只是拒绝接受他们破坏了规范 [1] 并搞砸了.因此,AppleScript 语言尽管存在所有其他缺陷,但仍然是唯一支持的解决方案,可以保证正确地说出 Apple 事件 [2].

Scripting Bridge is, at best, an 80/20/80 "solution" (i.e. 80% of the time it works, 20% of the time it fails, and 80% of the time you've no idea why). There's little point trying to argue with SB when it breaks on stuff that works perfectly well in AppleScript - the Apple engineers responsible designed it that way on purpose and simply refuse to accept they broke spec [1] and screwed up. As a result, the AppleScript language, for all its other deficiencies, remains the only supported solution that is guaranteed to speak Apple events correctly [2].

幸运的是,从 OS X 10.6 开始,有另一种选择:将 ObjC 用于所有常规编程内容,并且仅通过 AppleScript-ObjC 桥调用 AppleScript 以获取 IPC 内容.

Fortunately, since OS X 10.6 there has been another option available: use ObjC for all your general programming stuff, and only call into AppleScript via the AppleScript-ObjC bridge for the IPC stuff.

从您的 ObjC 代码的 POV 来看,您的基于 AppleScript 的 ASOC类"或多或少与常规 ObjC 类没有区别.它需要一些设置才能设置,并且您在过桥时会付出一些代价,但鉴于替代方案的残缺和不可靠的性质,它是任何非平凡的支持选项中最不可怕的.

From the POV of your ObjC code, your AppleScript-based ASOC 'classes' are more or less indistinguishable from regular ObjC classes. It requires a bit of fiddling to set up, and you'll pay a bit of a toll when crossing the bridge, but given the crippled, unreliable nature of the alternatives, it's the least horrid of the supported options for anything non-trivial.

假设您已经有一个现有的基于 ObjC 的项目,以下是向其中添加基于 ASOC 的类的方法:

Assuming you've already got an existing ObjC-based project, here's how to add an ASOC-based class to it:

  1. 在 Targets > APPNAME > Build Phases > Link Binary With Libraries 中,添加 AppleScriptObjC.framework.

在 Supporting Files > main.m 中,添加导入和加载行,如下所示:

In Supporting Files > main.m, add the import and load lines as shown:

#import <Cocoa/Cocoa.h>
#import <AppleScriptObjC/AppleScriptObjC.h>

int main(int argc, const char * argv[]) {
   [[NSBundle mainBundle] loadAppleScriptObjectiveCScripts];
   return NSApplicationMain(argc, argv);
}

  • 要定义可从 ObjC 调用的名为 MyStuff 的基于 ASOC 的类,请创建一个声明其公共方法的 MyStuff.h 接口文件:

  • To define an ASOC-based class named MyStuff that's callable from ObjC, create a MyStuff.h interface file that declares its public methods:

    // 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 文件:

    along with a MyStuff.applescript file containing its implementation:

    -- MyStuff.applescript
    
    script MyStuff
    
       property parent : class "NSObject"
    
       on square_(aNumber)
           return aNumber ^ 2
       end square_
    
    end script
    

  • 因为 MyStuff 类没有 ObjC 实现,链接器无法在构建时将您的 ObjC 代码链接到它.相反,使用 NSClassFromString() 在运行时查找类对象:

  • Because the MyStuff class doesn't have an ObjC implementation, the linker can't link your ObjC code to it at build-time. Instead, use NSClassFromString() to look up the class object at run-time:

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

    否则它与正常使用的原生 ObjC 类几乎没有区别:

    Otherwise it's pretty much indistinguishable from a native ObjC class in normal use:

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

  • HTH

    --

    [1] 在 AppleScript 最初发布后不久,Apple 管理层就解散了最初的 AppleScript 团队,导致其设计人员退出响应,因此丢失了很多关于这些东西应该如何工作的确切知识.特别是,应用程序开发人员在设计脚本支持时从未制定完整、正式的规范,因此他们所能做的就是使用个人判断和最佳猜测,然后针对 AppleScript 进行测试以检查它是否按预期工作.因此,AppleScript 自己的 Apple 事件桥接是事实上的规范,在过去的 20 年中,每个可编写脚本的应用程序都针对该规范实施,因此其他 AE 桥接器能够正常工作的唯一方法是,如果它们模仿AS 自己的桥梁到每一个最后的查询和怪癖 - 不幸的是,当前的 AS 团队反复未能理解[2].

    [1] Apple management broke up the original AppleScript team shortly after its initial release, causing its designers to quit in response, so a lot of knowledge of precisely how this stuff should work was lost. In particular, a full, formal specification was never produced for application developers to follow when designing their scripting support, so all they could do was use personal judgement and best guesses, then test against AppleScript to check it worked as hoped. Thus, AppleScript's own Apple event bridge is the de facto specification that every single scriptable app has been implemented against in the last twenty years, so the only way that other AE bridges can ever work correctly is if they mimic AS's own bridge down to every last query and quirk - a lesson, unfortunately, that the current AS team have repeatedly failed to understand [2].

    [2] JavaScript for Automation 的 Apple 活动支持同样糟糕和失败,顺便说一句.

    [2] JavaScript for Automation's Apple event supported is equally crappy and busted, incidentally.

    这篇关于Objective-C 脚本桥和 Apple 远程桌面的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

    查看全文
    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆