aardio 文档

完成、错误与图像反馈

不把提交当成功

SendCommand 通常同步,但在用户交互开始或从事件处理器调用时可能异步。PostCommand 排队执行;窗口消息返回值也不是绘图成功回执。IsQuiescent 只是空闲状态快照。

因此,以下做法不能证明特定任务完成:

这些低层接口不会自动形成带业务结果的事务。需要执行闭环时,优先使用本库的 CreateLispTask / RunLisp 任务接口:明确文档、保存请求 ID 与路径、读取终态回执,再验证几何结果。

重试和超时

  1. 只重试已确认尚未执行的临时忙碌拒绝或无副作用查询,并设置上限。
  2. 语法错误、参数错误应直接返回错误。
  3. 已提交但是否完成未知时,先查回执,不重放绘图、删除、保存。
  4. 超时不表示取消。CAD 仍可能稍后执行排队的任务。
  5. 不擅自发送 ESC、中止用户命令、关闭用户图纸或强制结束 CAD。
  6. Undo 分组是恢复辅助,不是保证完全回滚的通用事务。

com.cad.isCallRejected(err) 只识别 0x80010001 / 0x8001010A,不把普通“调用 null 方法”当作已拒绝接收。com.cad.callRetry(fn,timeout,...) 仅对已识别拒绝作有限重试,重试前按剩余预算延时,最多设为100毫秒;仅用于无副作用查询或单个可重试 COM 调用,不能包住多步写操作,否则前面已经完成的副作用可能重复。timeout 是从首次尝试起计的重试预算(毫秒),不是硬超时:callRetry(fn,2000) 不保证2秒内返回,无法中断阻塞的COM方法;timeout=0 仍会调用一次,也不保证立即返回。

任务的同步队列刷新 task.nudge() 默认不启用,要求原文档活动且 CAD 空闲;它不重发任务,也不等于取消。不要把许可证/系统阻塞当作程序死锁,或为解决等待问题无条件转为同步调用。完整约束见任务指南。

同步调用 CAD 时,不要让 CAD 又同步等待调用方;两边互相等待会死锁。LISP 启动外部 EXE 优先使用异步 startapp;参见对应范例。

LISP 续输等待与显式取消

命令行出现类似 ((_>、((((_> 或包含引号的续输提示时,应先检查表达式是否尚未读完整,不能直接判断为程序死锁。按回车可能只是继续提交空行,退格也不能撤回已经提交给解释器的上一行。

本机 AutoCAD 2026 实测:发送不完整的 (progn 后,IsQuiescent=false;此时再次用 COM SendCommand 发送两个 ESC 控制字符,被以 0x80010001 拒绝。后台投递 WM_KEYDOWN/WM_KEYUP 也未解除等待;确认 AutoCAD 为前台后,用 key.press("ESC") 模拟两次真实按键成功恢复空闲。这是该环境下验证的恢复路线,不保证适用于所有忙碌、模态对话框或死锁。

只有调用方明确授权中止当前操作时,才应尝试此恢复方式:

  1. 在空闲时从 COM 应用的 cad.HWND 获取并缓存原目标 CAD 实例 HWND;文档窗口为 doc.HWND,不要混用。不要向所有 CAD 窗口广播,也不要通过 AutoCAD 专用类名去猜兼容 CAD 的窗口。
  2. 需要时还原窗口、置于前台,并检查 win.getForeground()==hwnd。激活失败时停止,不向其他应用发送按键。
  3. key.press("ESC"),再按一次,随后有限等待并重新读取状态。
  4. 恢复空闲只表示可以继续操作,不表示原任务成功、已回滚或没有部分执行;仍须查询回执和图纸。
  5. 如果恢复失败,返回给调用方决定是否重启。库不自动强杀进程。

显式恢复可调用 com.cad.cancelCommand(hwnd,activate):默认 activate=false,不抢前台;明确授权后设为 true 可尝试还原并激活原窗口。函数逐次检查前台窗口与修饰键,失败返回 null,err,成功仅表示两次 Esc 已发送。不访问忙碌的 COM,不要求窗口类名,也不自动重启 CAD。

不建议用 Ctrl+A 作为取消协议,它可能触发全选。当前 winex 的标题参数 "" 是精确匹配空标题,省略/null 才忽略标题;非空标题使用模式匹配。旧版本规则可能不同。无论何种规则,仅 WPF 类名与空标题都不足以跨 CAD 产品/版本识别命令输入区,应优先缓存 COM 提供的主窗口 HWND。

宿主进程原生崩溃与 CAD 续输等待是两类问题。语言级 call/try 不能保证捕获原生访问冲突。若某旧接口疑似引发宿主崩溃,应在独立工作进程中隔离诊断,保存每次提交前的任务目录和阶段;不要在自动化主进程里反复调用可疑接口。GetLispFunctions/LispExp 不参与新任务执行链路。

图像与几何数据互补

图像用于查看布局、遮挡、文字效果;实体数量、坐标、半径、图层与包围盒用于确定性验收。图片“看起来对”不等于几何尺寸正确。

首选 cad.Preview(handles,doc,{zoom="handles"}):标准库统一完成非空验证、BMP→PNG、临时缩放与恢复,返回viewRestored/cleanupWarning。技能没有另一份实现。

了解底层时的无需桌面截图路线:

  1. 明确目标 doc 和视图;在必要时统一重生成。
  2. 创建唯一命名的非空 SelectionSet,添加本次需要查看的实体。
  3. doc.Export(baseFilename,"BMP",selection)。
  4. 删除 SelectionSet(不是删除其中的实体)。
  5. 用 gdip.bitmap 读取 BMP 并保存 PNG,返回实际宽高和文件路径。

完整示例见 原生图像导出。WMF/BMP 导出传入空 SelectionSet 会转入交互选择,可能一直等待用户输入;无人值守调用前应加入目标实体并确认 Count>0,不用空集做“最小探针”。PNG 转换不增加源图细节,也不是任意分辨率离屏渲染。

生成了文件不代表画面是最新的。 在 AutoCAD 2026 的边界测试中,窗口置于后台后重生成,导出图像能反映新实体;最小化后新增实体再导出,所得 PNG 却与之前完全相同,直到还原窗口并重生成才更新。因而范例拒绝最小化状态;正式自动化应在取得授权后还原原窗口、明确目标文档/布局并重生成,再导出和核对。不要把最小化导出当作可靠的离屏渲染。普通模型视图和图纸空间均完成过导出测试,但不同 CAD、视觉样式、DPI 等仍须分别验证。

临时缩放后恢复视图时,要区别坐标系:VIEWCTR 是 UCS 中心,ActiveX ZoomCenter/ZoomWindow 接收 WCS 点;可用 Utility.TranslateCoordinates 转换。不要直接复用可能滞后的 ActiveViewport Center/Height 属性作为当前视图快照。恢复后按浮点容差回读中心与高度,失败保留清理警告,不把改变后的视图作为新的“原视图”重试整个导出。

这里不要求 .NET 插件,也未提供视频流。需要过程反馈时,优先记录关键步骤的静帧和对应的结构化几何结果。

旧路线的边界

官方参考

Markdown 格式