Objective-C脚本桥和Apple远程桌面
尝试通过Objective-C中的脚本桥自动查看Apple Remote Desktop中的计算机,方法如下:Objective-C脚本桥和Apple远程桌面,objective-c,cocoa,applescript,scripting-bridge,Objective C,Cocoa,Applescript,Scripting Bridge,尝试通过Objective-C中的脚本桥自动查看Apple Remote Desktop中的计算机,方法如下: @try { SBApplication *RD = [SBApplication applicationWithBundleIdentifier:@"com.apple.RemoteDesktop"]; // (code to check for ARD running and installed omitted here)
@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和导入远程桌面.h)都已执行-类型转换是为了避免在构建时出现不可避免的链接时间错误
编辑1:阅读关于SBObject(RemoteDesktopComputer的父对象)的文档时说,它是一个引用,而不是一个实际实例,您可以通过调用SBObject的get方法(返回id)获取它。所以我也试着运行这个,但不幸的是得到了同样的结果:
[[computer get] observeZooming:Nil];
以下是有关SBObject的文档:
仍在尝试…脚本桥是一个有缺陷的、模糊的混乱,因此当应用程序命令无法工作时,您不知道问题是SB有缺陷还是应用程序本身有缺陷,或者只是要求您以不同的方式对其进行表述 因此,第一步是在AS中编写测试脚本,以查看它是否在AS中工作。如果是这样的话,那就是某人在胡说八道;如果没有,请尝试修改您的AS代码(例如,尝试以不同的方式使用
at
参数的引用,或者完全忽略它),直到完成为止
你还应该询问苹果的AppleScript用户和ARD邮件列表,以及ARD脚本编写者可能会去的任何其他地方,因为大多数应用程序的脚本编写文档都严重不足,所以很多关于如何操作的知识都是口耳相传的。(你真正想找的人是John C Welch,又名@bynkii
,因为他是ARD脚本的大师。)(FWIW,我已经有了以下的写作方法,所以我将其留在这里以备将来参考。)
如何使用AppleScript ObjC代替脚本桥 脚本桥充其量是一个80/20/80“解决方案”(即80%的时间工作,20%的时间失败,80%的时间你不知道为什么)。当某人在AppleScript中工作得非常好的东西上出现问题时,试图与他争论是没有什么意义的——负责设计的苹果工程师故意这样做,只是拒绝接受他们违反了规范[1]并搞砸了。因此,尽管AppleScript语言存在其他缺陷,但它仍然是唯一能够保证正确说出Apple事件的受支持解决方案[2] 幸运的是,自OSX10.6以来,还有另一个选项可用:对所有常规编程内容使用ObjC,对IPC内容只通过AppleScript ObjC桥调用AppleScript 从ObjC代码的角度来看,基于AppleScript的ASOC“类”与常规ObjC类几乎没有区别。它需要一点摆弄来设置,而且过桥时你要付一点通行费,但是考虑到备选方案的残废和不可靠性质,它是支持的选项中最不可怕的一个,对于任何非琐碎的东西 假设您已经有一个基于ObjC的现有项目,下面介绍如何向其中添加基于ASOC的类:
AppleScriptObjC.framework
main.m
中,添加导入和加载行,如图所示:
#import <Cocoa/Cocoa.h>
#import <AppleScriptObjC/AppleScriptObjC.h>
int main(int argc, const char * argv[]) {
[[NSBundle mainBundle] loadAppleScriptObjectiveCScripts];
return NSApplicationMain(argc, argv);
}
以及包含其实现的MyStuff.applescript
文件:
-- MyStuff.applescript
script MyStuff
property parent : class "NSObject"
on square_(aNumber)
return aNumber ^ 2
end square_
end script
MyStuff
类没有ObjC实现,所以链接器无法在构建时将您的ObjC代码链接到它。相反,请使用NSClassFromString()
在运行时查找类对象:
#import "MyClass.h"
...
MyStuff *stuff = [[NSClassFromString(@"MyStuff") alloc] init];
否则,它与正常使用中的本机ObjC类几乎没有区别:
NSNumber *result = [stuff square: @3];
NSLog(@"Result: %@", result);
[2] 顺便说一句,Automation的Apple event支持的JavaScript同样差劲且失败。您能检查哪个函数抛出异常(例如,通过使用异常断点)吗?进入observeZooming:只需像不使用断点一样抛出异常,确认observeZooming:确实是触发异常的方法,但没有给出任何关于原因的见解。查看我的编辑-尝试使用和不使用“get”选择器来取消引用对象,每次都得到相同的结果我没有使用脚本桥,因此我可能无法想出解决方案,但
[RD computers]
的返回值是否为非零?我使用NSLog输出运行了一些测试代码来检查,它确实不是零。。。但是,这可能是因为一些正在进行的去引用抽象——请查看以下详细解释:非常有用,谢谢!希望这对其他人有帮助。
NSNumber *result = [stuff square: @3];
NSLog(@"Result: %@", result);