3

我一直用这个把头撞在墙上。我正在尝试使用脚本桥在 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)>

自动文本条目指示为“未来”。有任何想法吗?提前致谢!

4

3 回答 3

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"];
于 2013-08-23T14:46:55.510 回答
0

@Philp Regan:我测试了您的代码 - 令人惊讶的是 - 它不起作用:创建所需的“自动文本输入”对象。也许如果您没有包含if在元素创建中默默隐藏任何失败的块,您可能自己已经注意到了这一点。

这是我的测试从您的原始 ObjC 代码翻译成 Python - 不幸的是,我无法使用您的 ObjC 代码,因为sdp在尝试为 Word 2011 创建胶水标题时呕吐(sdp也像蚁丘一样有问题,并且在 InDesign 和其他应用程序上搞砸了出色地)。

#!/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

如您所见,该auto text entry元素创建;此外,SB 静默失败,让您不知道为什么操作不起作用。

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

只是为了证明这是 SB 的错,而不是其他的错,这里是 Python appscript 中的等效代码,只是为了提供make命令at参数的正确参考形式而进行了调整:

#!/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

...

再次:Scripting Bridge 和 sdp 无法正常工作;从来没有,永远不会。除了常见的错误和遗漏之外,SB 的设计存在根本缺陷:作为一个 ORM,它试图将 Cocoa 狭窄的 OO 语义强加于 Apple 事件的广泛 RPC + 关系查询语义,从而在两者之间造成严重的阻抗不匹配。(这是 80/20/80 问题:80% 的时间它有效,但 20% 的时间它不起作用,80% 的时间你不知道为什么。)有很多 SB 失败的例子由于它对应用程序脚本的实际工作方式做出的所有有缺陷或不正确的假设,因此在 AppleScript 和 appscript 中完美运行的命令。

一些引用和命令甚至根本无法构造 - 例如,尝试将以下内容转换为 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

第一个示例将无法编译,因为 SB 无法构造该every file of entire contents部分,因为它只能引用具体对象(文件、文件夹、磁盘等)的属性和元素 - 并且该entire contents属性包含引用(对象说明符),而不是一个具体的对象。

第二个将失败,因为它无法构造该部分:after paragraph 2负责 SB 的 Apple 开发人员只是忘记实现构造插入位置引用所需的适当的 /// 方法beforeafterbeginningend

OP 的 Word 示例特别具有讽刺意味,因为在 SB 发布后的几天内就向 Apple 报告了根本问题:SB-[NSElementArray addObject:]只知道如何构造makeform 的事件make new <element> at end of <elements> ...。但是,在 Apple 事件世界中,以下形式也是完全合法的:make new <element> at <element> ...make new <element> at <property> ...make new <element> at <elements> ...make new <element> at end of <property> ...,可能还有其他一些形式。

特定应用程序可以理解哪些形式,哪些不可以由应用程序本身决定。脚本接口建立在 Cocoa Scripting 之上的应用程序都理解这种make new <element> at end of <elements> ...形式;但是,其脚本接口直接构建在 Carbon Apple 事件管理器 API 或各种定制或第三方 C/CC+ 框架上的应用程序通常差异很大。

例如,Finder、iTunes、Illustrator 和 Word 等基于 Carbon 的应用程序通常要求您说make new <element> at <elements> ...,但 SB 不允许您构建这些表单。如果您尝试使用 SB's -[NSElementArray addObject:],应用程序会抛出错误,因为它不理解make new <element> at end of <elements> ...表单。(然后 SB 会默默地消除该错误,因为它的错误报告也很糟糕。)

负责 SB 的 Apple 开发人员甚至承认它无法为这些应用程序的make处理程序构建正确的参考表单。他的“解决方案”是破解在专门与 Finder 和 iTunes 对话时导致-addObject:组合事件的一次性解决方法。make new <element> at <elements> ...不用说,这并没有解决根本问题,所以六年和四个主要操作系统版本之后,其他应用程序继续打破这个任何其他愚蠢的 SB 设计缺陷。

...

这些甚至不是困难或晦涩的用例——它们是基本的 Apple Events 101 东西。所以苹果真的没有理由把 SB 搞到这种程度:尤其是当他们可以开放访问所有内部 AppleScript 实现和文档时,更不用说至少六个第三方背后的所有代码和知识从优秀到糟糕的桥梁,从中学习 Apple 活动编程的所有注意事项。正如我在其他地方所说,这已经是一个已解决的问题:SB 再次完全解决了它。

SB 根本无法说出 Apple 事件,因为它们实际上是由真实用户依赖于执行实际工作真实应用程序现实世界中说出的。真正的应用程序脚本通常是混乱的、不一致的、被含糊的或有缺陷的字典所困扰,并且严重缺乏硬性规范、健壮、称职的框架,或者该死的开发人员或用户文档。但是,SB 并没有接受这个令人不快的现实并为用户提供有时不吸引人但能胜任的工具来可靠地处理它,而是决定将整个烂摊子扫到 ORM 地毯下,并假装它不存在。

对于那些仅将 SB 用于琐碎应用程序的琐碎工作的用户来说,这可能很好,因此永远不要将其推到足够多的缺陷和缺点跳出来咬他们。但对于我们这些从事真正专业自动化工作的人来说,SB 只是一个糟糕的笑话,它对 AppleScript 世界的倒退比 Apple 什么都没做。

于 2013-08-26T13:47:55.627 回答
-1

SB 不能正常工作;从来没有,永远不会。它特别容易出现与 Word 等基于 Carbon 的应用程序的兼容性问题,这些应用程序在构建引用和命令的方式上具有更大的可变性,尽管即使是 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 苦差事。

有关更多信息,请参阅这些帖子:

将变量或字符串从 OS X Cocoa 应用程序传递到 Applescript

在 Mac 应用程序中执行 AppleScript 文件?

...

我得到这个输出:[...]自动文本条目被指示为“未来”。有任何想法吗?

这只是 SB 的伪 OO 伪造品泄露出去。忽略它; 它只是令人困惑,无论如何与您的问题无关。

于 2013-07-16T21:21:04.633 回答