EA JavaScript生成RTF文件时提示"Failed to save the output file"的问题解决咨询
EA JavaScript生成RTF文件时提示"Failed to save the output file"的问题解决咨询
我目前遇到一个Enterprise Architect(EA)脚本的问题,想请大家帮忙分析解决:
我需要把EA项目里的图表导出到一个无法用EA直接生成的外部Word文档中,其他编辑这个Word的人也不需要有EA项目权限。我的做法是写了一段EA JavaScript脚本,给每个图表生成单独的RTF文件,然后在主Word文档里通过链接插入这些RTF。
一开始一切正常,但过了一段时间后,运行docGenerator.SaveDocument时会弹出**"Failed to save the output file"**的错误。我排查后发现:
- 只有当这些RTF文件被Word文档作为链接引用后,才会出现保存失败的情况;如果不把RTF链接到Word,我可以无限次重新生成RTF
- 我从来没有直接用Word打开过这些RTF文件(怕Word锁定文件),而且生成RTF时主Word文档也是关闭的
- 之前用其他工具生成RTF并做同样的链接操作时,完全没有这个问题,所以我怀疑是EA的RTF生成机制导致的文件锁定或保护问题
我的核心需求是:
- 如何绕过EA在保存RTF时的文件保护,成功覆盖被Word链接引用过的RTF文件?
- 有没有其他EA的API或方法可以替代
docGenerator.SaveDocument来导出图表为RTF?
以下是我当前脚本中生成RTF的关键代码片段:
function OnProjectBrowserScript() { // Get the type of element selected in the Project Browser var treeSelectedType = Repository.GetTreeSelectedItemType(); switch ( treeSelectedType ) { case otPackage : { // Code for when a package is selected // [...] 省略其他逻辑 packageDiagrams = thePackage.Diagrams; // Collection of all the Diagrams for ( var i = 0 ; i < packageDiagrams.Count ; i++ ) { var currentDiagram as EA.Diagram; currentDiagram = packageDiagrams.GetAt( i ); // Document Generation using docGenerator var docGenerator as EA.DocumentGenerator; docGenerator = Repository.CreateDocumentGenerator(); docGenerator.NewDocument("") docGenerator.DocumentDiagram(currentDiagram.DiagramID,1,"Diagram Report"); var diagramName = currentDiagram.Name + ".rtf"; //Save diagram into rtf document var saveSuccess = docGenerator.SaveDocument( diagramName, EA.DocumentType.dtRTF ); if ( saveSuccess ) { Session.Prompt( "Documentation complete!", promptOK ); } else { // -- > Error message saying file cannot be saved <-- Session.Prompt( "Error saving file " + diagramName + " : " + docGenerator.GetLastError(), promptOK ); } } break; } // [...] 省略其他分支 } }
我自己梳理的可能解决方案方向,也想听听大家的建议
1. 优化文件处理和资源释放逻辑
EA的DocumentGenerator可能没有彻底释放文件资源,导致后续覆盖时被锁定。可以尝试:
- 生成RTF前,先检查目标文件是否存在,若存在则尝试先删除(用
FileSystemObject处理,捕获锁定异常) - 每次循环结束后显式销毁
docGenerator对象,强制释放资源 - 始终使用完整路径保存文件,避免EA默认路径的权限或缓存问题
示例代码片段:
// 引入文件系统对象 var fso = new ActiveXObject("Scripting.FileSystemObject"); // 获取EA模型的根路径,确保导出路径固定 var modelRootPath = Repository.GetModelPath(); for ( var i = 0 ; i < packageDiagrams.Count ; i++ ) { var currentDiagram = packageDiagrams.GetAt( i ); var diagramName = currentDiagram.Name + ".rtf"; var fullSavePath = modelRootPath + diagramName; // 先尝试删除旧文件(如果未被锁定) if (fso.FileExists(fullSavePath)) { try { fso.DeleteFile(fullSavePath, true); } catch(e) { Session.Prompt("无法覆盖旧文件:" + fullSavePath + ",错误:" + e.message, promptOK); continue; } } // 文档生成逻辑 var docGenerator = Repository.CreateDocumentGenerator(); docGenerator.NewDocument("") docGenerator.DocumentDiagram(currentDiagram.DiagramID,1,"Diagram Report"); var saveSuccess = docGenerator.SaveDocument( fullSavePath, EA.DocumentType.dtRTF ); if ( saveSuccess ) { Session.Prompt( "Documentation complete!", promptOK ); } else { Session.Prompt( "Error saving file " + fullSavePath + " : " + docGenerator.GetLastError(), promptOK ); } // 显式销毁对象 docGenerator = null; }
2. 换用直接导出图表的API替代DocumentGenerator
EA提供了Diagram.Export方法,可以直接导出图表为RTF,跳过文档生成的流程,可能避免文件锁定问题:
var fullSavePath = modelRootPath + currentDiagram.Name + ".rtf"; // 直接导出图表为RTF var exportSuccess = currentDiagram.Export( fullSavePath, "RTF", 1, // 导出质量(1为最高) 0, 0, // 宽度高度设为0表示使用图表原始尺寸 true, // 是否包含图例 false // 是否导出为黑白 ); if (exportSuccess) { Session.Prompt("图表导出成功:" + fullSavePath, promptOK); } else { Session.Prompt("图表导出失败:" + fullSavePath, promptOK); }
这个方法生成的RTF是纯图表内容,和DocumentGenerator生成的带"Diagram Report"模板的RTF格式有差异,但更轻量化,适合只需要插入图表的场景。
3. 排查Word的后台缓存锁定
虽然关闭了主Word,但Word可能在后台保留了链接文件的缓存句柄。可以尝试:
- 生成RTF前,结束所有
WINWORD.EXE进程,确保没有残留的文件锁定 - 将RTF导出到一个独立的、非Word默认访问的目录,避免Word的自动缓存机制影响
备注:内容来源于stack exchange,提问作者lctdim
相关产品推荐
相关产品推荐

