@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 开发人员只是忘记实现构造插入位置引用所需的适当的 /// 方法before
!after
beginning
end
OP 的 Word 示例特别具有讽刺意味,因为在 SB 发布后的几天内就向 Apple 报告了根本问题:SB-[NSElementArray addObject:]
只知道如何构造make
form 的事件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 什么都没做。