OBJ-C脚本桥 - 无法创建具有属性的脚本对象(Microsoft Word)

时间:2013-07-16 20:27:57

标签: objective-c cocoa scripting applescript scripting-bridge

我一直用这个撞在墙上。我正在尝试使用脚本桥在MS Word中创建一个新的自动文本条目。

以下是我尝试使用的代码:

wordApplication *theWordApp = [SBApplication applicationWithBundleIdentifier:@"com.microsoft.Word"];
wordTemplate *theWordTemplate = [[theWordApp activeDocument] attachedTemplate];
wordAutoTextEntry *theNewAutoTextEntry = [[[theWordApp classForScriptingClass:@"auto text entry"] alloc] init];
[[theWordTemplate autoTextEntries] addObject:theNewAutoTextEntry];
[theNewAutoTextEntry setName:@"test name"];
NSLog(@"%@", [theNewAutoTextEntry name]);

使用此,我收到以下错误:

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

我也尝试过:

wordApplication *theWordApp = [SBApplication applicationWithBundleIdentifier:@"com.microsoft.Word"];
wordTemplate *theWordTemplate = [[theWordApp activeDocument] attachedTemplate];
wordAutoTextEntry *theNewAutoTextEntry = [[[theWordApp classForScriptingClass:@"auto text entry"] alloc] initWithProperties:[NSDictionary dictionaryWithObjectsAndKeys:@"testname", @"test", nil]];
NSLog(@"%@", [theNewAutoTextEntry name]);

我这样得到同样的错误。

有趣的是,当我运行以下内容时:

wordApplication *theWordApp = [SBApplication applicationWithBundleIdentifier:@"com.microsoft.Word"];
wordTemplate *theWordTemplate = [[theWordApp activeDocument] attachedTemplate];
wordAutoTextEntry *theNewAutoTextEntry = [[[theWordApp classForScriptingClass:@"auto text entry"] alloc] init];
NSLog(@"%@", theNewAutoTextEntry);

我得到了这个输出:

<future MicrosoftWordAutoTextEntry with properties (null)>

自动文本条目表示为“future”。有任何想法吗?提前谢谢!

3 个答案:

答案 0 :(得分:2)

你是在正确的轨道上,但似乎没有从它的数组获取对象,这是使用它所必需的。最好使用name属性初始化对象以确保轻松检索。就是......

    word011 *theWordApp = [SBApplication applicationWithBundleIdentifier:@"com.microsoft.Word"];
    word2011Template *theWordTemplate = [[theWordApp activeDocument] attachedTemplate];

    // create the object with them name property to grab it later
    NSString *testName = @"test name";
    word2011AutoTextEntry *theNewAutoTextEntry = [[[theWordApp classForScriptingClass:@"auto text entry"] alloc] initWithProperties:[NSDictionary dictionaryWithObjectsAndKeys:testName, @"name", nil]];
    [[theWordTemplate autoTextEntries] addObject:theNewAutoTextEntry];

    // you created the object, but now you have to actually *get* the object
    // check for existence first other EXC_BAD_ACCESS will happen
    if ( [[[theWordTemplate autoTextEntries] objectWithName:testName] exists] {
        theNewAutoTextEntry = [[theWordTemplate autoTextEntries] objectWithName:testName];
    }

    // name already set, so you can move with working with the object
    //[theNewAutoTextEntry setName:@"test name"];

答案 1 :(得分:0)

@Philp Regan:我测试了你的代码 - 惊喜 - 它不起作用:所需的自动文本条目&#39;对象创建。也许如果你没有包含静默隐藏元素创建失败的if块,你可能已经注意到了这一点。

我的测试从原始的ObjC代码转换为Python - 遗憾的是,我无法使用您的ObjC代码,因为sdp在尝试为Word 2011创建粘合标头时遇到了问题({{1像蚁丘一样也是错误的,并且在InDesign和其他应用程序上也搞砸了。)

sdp

如您所见,#!/usr/bin/python from ScriptingBridge import * theWordApp = SBApplication.applicationWithBundleIdentifier_("com.microsoft.Word") theWordTemplate = theWordApp.activeDocument().attachedTemplate() testName = "test name 99" theNewAutoTextEntry = theWordApp.classForScriptingClass_("auto text entry").alloc().initWithProperties_(NSDictionary.dictionaryWithObjectsAndKeys_(testName, "name", None)) theWordTemplate.autoTextEntries().addObject_(theNewAutoTextEntry) print theWordTemplate.autoTextEntries().objectWithName_(testName).exists() # prints: False (!) print theWordApp.lastError() # prints: None 元素不是已创建;此外,SB无声地失败,让你不知道为什么操作不起作用。

(如果您愿意,我很乐意使用您自己创建的Word.h文件重试原始的ObjC代码,但它会产生完全相同的结果。)

只是为了证明这是SB的错,而不是其他任何事情,这里是Python appscript中的等效代码,仅调整为auto text entry命令提供正确的引用形式&# 39; s make参数:

at

...

再一次:Scripting Bridge和sdp不能正常工作;永远不会,永远不会。除了通常的错误和遗漏之外,SB的设计存在根本缺陷:作为一个ORM,它试图将Cocoa的OO语义强加给Apple事件&#39;广泛的RPC +关系查询语义,在两者之间造成严重的阻抗不匹配。 (这是80/20/80的问题:它有80%的时间可以工作,但有20%的时间没有,80%的时间你都不知道为什么。)有许多SB失败的命令在AppleScript和appscript中完美运行,因为它对应用程序脚本实际工作的所有有缺陷或不正确的假设。

有些参考和命令甚至根本无法构建 - 例如,尝试将以下内容转换为SB:

#!/usr/local/bin/python3

from appscript import *

theWordApp = app(id="com.microsoft.Word")

theWordTemplate = theWordApp.active_document.attached_template

testName = "test name 101"

theNewAutoTextEntry = theWordApp.make(new=k.auto_text_entry, at=theWordTemplate, with_properties={k.name: testName})

print (theWordTemplate.auto_text_entries[testName].exists()) # prints: True

第一个例子将无法编译,因为SB不能构造tell application "Finder" get name of every file of entire contents of desktop end tell tell application "TextEdit" tell document 1 duplicate paragraph 1 to after paragraph 2 end tell end tell 部分,因为它只能引用具体对象(文件,文件夹,磁盘等)的属性和元素 - 以及every file of entire contents属性包含引用(对象说明符),而不是具体对象。

第二个会失败,因为它无法构建entire contents部分:负责SB的Apple开发人员忘记实施相应的after paragraph 2 / before / {{1构造插入位置引用所需的/ after方法!

OP的Word示例特别具有讽刺意味,因为在SB发布的几天内向Apple报告了潜在的问题:SB beginning只知道如何构建{{1}形式end的事件。但是,在Apple活动世界中,以下表单也是完全合法的:-[NSElementArray addObject:]makemake new <element> at end of <elements> ...make new <element> at <element> ...以及其他一些表单。

特定应用程序将理解哪种形式,以及它不会由应用程序本身决定。脚本接口基于Cocoa脚本构建的应用程序都理解make new <element> at <property> ...形式;但是,脚本接口直接构建在Carbon Apple Event Manager API或各种定制或第三方C / CC +框架上的应用程序通常差异很大。

例如,像Finder,iTunes,Illustrator和Word这样的基于碳的应用程序通常要求您说make new <element> at <elements> ...,但SB不允许您构建这些表单。如果您尝试使用SB make new <element> at end of <property> ...,则应用程序会抛出错误,因为它不了解make new <element> at end of <elements> ...表单。 (并且SB然后默默地压制该错误,因为它的错误报告也很糟糕。)

负责SB even admitted it was incapable的Apple开发人员为这些应用程序构建正确的参考表格&#39; make new <element> at <elements> ...处理程序。他的解决方案&#34;是专门讨论Finder和iTunes时,导致-[NSElementArray addObject:]汇集make new <element> at end of <elements> ...事件的一次性变通办法。毋庸置疑,这并没有解决潜在的问题,所以六年后和四个主要的操作系统发布后,其他应用程序继续打破这个任何许多其他愚蠢的SB设计缺陷。

...

这些甚至不是困难或模糊的用例 - 它们是基本的Apple Events 101。所以Apple真的没有理由将SB搞砸到这个程度:特别是当他们可以开放访问所有内部AppleScript实现和文档时,更不用说至少有六个第三方背后的所有代码和知识了从优秀到糟糕的桥梁,从中学习Apple事件编程的所有Do和Don。正如我在其他地方所说的那样,已经解决了一个问题:它让SB完全解决了它。

SB根本无法说出Apple事件,因为真实用户所依赖的真实应用实际上是在现实世界中说出来的做实际工作。真正的应用程序脚本通常是混乱的,不一致的,困扰着模糊或错误的词典以及可怕的缺乏硬性规范,强大,有能力的框架,或者值得一试的开发人员或用户文档。但是,SB并没有接受这种令人不快的现实,并且为用户提供了有时候没有吸引力但却很有能力的工具来可靠地处理它,而是决定在ORM地毯下扫除整个混乱,并假装它不存在。

对于那些仅使用SB进行琐碎的应用程序工作的用户来说,这可能没什么用,所以从来没有足够的因为其无数的缺陷和缺点而跳出来咬它们。但是对于我们这些从事真正的专业自动化工作的人来说,SB只是一个糟糕的笑话,比苹果公司什么也不做任何事情都更能阻止AppleScript世界。

答案 2 :(得分:-1)

SB无法正常工作;永远不会,永远不会。它特别容易出现与基于碳的应用程序(如Word)的兼容性问题,这些应用程序在构造引用和命令方面具有更大的可变性,尽管即使是Cocoa应用程序也会给它带来gyp。

以下是AppleScript中如何完美运行的方法:

tell application "Microsoft Word"
    make new auto text entry at attached template of active document ¬
        with properties {name:"test name", auto text value:"test value"}
end tell

但是,将其转换为SB代码只会在下一行产生“选择器未识别”错误,因为SB无法构造所需的参考形式:

[theWordTemplate addObject:theNewAutoTextEntry];

假设您的目标是10.6或更高版本,请忘记SB并使用AppleScript-ObjC桥。 AppleScript是唯一仍然支持的解决方案,它知道如何正确地谈论Apple事件。 ASOC使AppleScript脚本对象作为普通的Cocoa类和实例出现在应用程序的其余部分,允许您的ObjC代码直接与AppleScript对话,反之亦然,从而避免了SB缺陷和NSAppleScript苦差事。

请参阅以下帖子了解更多信息:

Pass Variable or String from OS X Cocoa App to Applescript

Execute AppleScript file in Mac app?

...

  

我得到这个输出:[...]自动文本条目表示为“future”。有什么想法吗?

这只是SB的伪OO伪造漏掉了。忽略它;无论如何,它只会让你感到困惑并与你的问题无关。