# 完成、错误与图像反馈

## 不把提交当成功

`SendCommand` 通常同步，但在用户交互开始或从事件处理器调用时可能异步。`PostCommand` 排队执行；窗口消息返回值也不是绘图成功回执。`IsQuiescent` 只是空闲状态快照。

因此，以下做法不能证明特定任务完成：

- SendCommand/PostCommand 返回后立即宣称成功；
- 固定 sleep 若干秒；
- 看到一次 IsQuiescent=true；
- 收到 WM_COPYDATA 返回值。

这些低层接口不会自动形成带业务结果的事务。需要执行闭环时，优先使用本库的 [CreateLispTask / RunLisp 任务接口](tasks.html)：明确文档、保存请求 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 空闲；它不重发任务，也不等于取消。不要把许可证/系统阻塞当作程序死锁，或为解决等待问题无条件转为同步调用。完整约束见[任务指南](tasks.html)。

同步调用 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 插件，也未提供视频流。需要过程反馈时，优先记录关键步骤的静帧和对应的结构化几何结果。

## 旧路线的边界

- WM_COPYDATA 使用旧的同步 SendMessage，目标不响应时可能阻塞；不推荐作为 AI 的主要任务通道。
- [CompileCSharp](csharp.html) 已替代 NetCompiler：自动区分旧 Framework 和现代 SDK 编译，返回唯一 DLL 路径及诊断；编译与加载分开，不提供热卸载。
- NetLoad 无需安全选项：CAD 允许时内部临时调整并恢复，受限时保留原生提示或拒绝。程序集要与目标 CAD 运行时匹配。

## 官方参考

- [SendCommand](https://help.autodesk.com/cloudhelp/2026/ENU/AutoCAD-ActiveX-Reference/files/GUID-E13A580D-04CA-46C1-B807-95BB461A0A57.htm)
- [PostCommand](https://help.autodesk.com/cloudhelp/2026/ENU/AutoCAD-ActiveX-Reference/files/GUID-9D3B8666-1B40-47C0-911B-859E3C38FB1A.htm)
- [Document.Export](https://help.autodesk.com/cloudhelp/2026/ENU/AutoCAD-ActiveX-Reference/files/GUID-893F1711-3591-4DDC-8D27-DF91052F5E5A.htm)
- [AddHatch](https://help.autodesk.com/cloudhelp/2026/ENU/AutoCAD-ActiveX-Reference/files/GUID-BAF2BEDD-489A-42D1-92B1-698DC9DAE675.htm)
- [AutoLISP 字符串控制字符](https://help.autodesk.com/cloudhelp/2024/ESP/AutoCAD-AutoLISP/files/GUID-C8E55E82-0104-4305-95E5-1671628A2FF3.htm)
