前言
在工程建设与制造业数字化转型的浪潮中,我们经常面临一个架构难题:业务流在 Web 端(SaaS 系统、AI 生成内容),而生产流在桌面端(AutoCAD、Revit)。
如何将 Web 端生成的数据(如设计说明、BOM 表、AI 生成的布局方案)无缝传输到 AutoCAD 并自动生成图纸?传统的做法是“导出 Excel/JSON -> 人工打开 CAD -> 导入插件”,效率低下且割裂。
本文将分享我在最近一个项目中采用的**“本地伴随服务(Local Sidecar Server)”**技术方案。通过在 AutoCAD 插件内部嵌入轻量级 Web Server,实现了 Web 页面点击按钮,AutoCAD 自动唤醒并完成绘图的全自动化流程。
1. 架构设计思路
AutoCAD 的 .NET API 是基于 COM 的单线程模型,而 Web 通信通常是异步多线程的。要打通这两者,核心在于解决通信协议与线程封送(Marshaling)。
整体架构图
graph LR
A[Web 前端/SaaS系统] -- HTTP POST (JSON) --> B[本地 HTTP Server (localhost:19090)]
subgraph AutoCAD 进程
B -- 1. 接收请求 --> C[请求队列/上下文]
D[AutoCAD 主线程] -- 2. 轮询/事件触发 --> C
D -- 3. 执行绘图逻辑 --> E[DWG 图纸]
end
核心组件:
Web 端:发送包含绘图数据(Markdown/JSON)和模板信息的 HTTP 请求。AutoCAD 插件(Server 端):
使用 搭建轻量级服务。监听本地特定端口(如
System.Net.HttpListener)。处理跨域(CORS)问题,允许浏览器直接调用。
19090
线程同步机制:将 HTTP 线程接收到的数据安全地转移到 AutoCAD 主 UI 线程执行。
2. 核心代码实现
2.1 嵌入式 HTTP Server
我们在插件初始化时启动一个异步的 HTTP Listener。这里使用了 .NET 8 的新特性,代码简洁高效。
// WebServer.cs 核心片段
public class WebServer : IDisposable
{
private readonly HttpListener _listener = new HttpListener();
private const string UrlPrefix = "http://localhost:19090/";
public void Start()
{
if (!HttpListener.IsSupported) return;
_listener.Prefixes.Add(UrlPrefix);
_listener.Start();
// 开启异步监听循环
Task.Run(async () => {
while (_listener.IsListening)
{
var context = await _listener.GetContextAsync();
ProcessRequest(context);
}
});
}
private void ProcessRequest(HttpListenerContext context)
{
// 1. 处理 CORS,允许 Web 端跨域调用
context.Response.Headers.Add("Access-Control-Allow-Origin", "*");
context.Response.Headers.Add("Access-Control-Allow-Methods", "POST, GET, OPTIONS");
if (context.Request.HttpMethod == "OPTIONS")
{
context.Response.Close();
return;
}
// 2. 解析 POST 数据
using var reader = new StreamReader(context.Request.InputStream, context.Request.ContentEncoding);
string json = reader.ReadToEnd();
// 3. 反序列化请求对象
var requestData = JsonSerializer.Deserialize<ImportRequest>(json);
// 4. 存入静态上下文,供 AutoCAD 主线程读取
ImportContext.CurrentRequest = requestData;
// 5. 关键一步:通知 AutoCAD 主线程执行命令
// 注意:这里不能直接调用绘图 API,必须通过命令队列或 SendStringToExecute
var doc = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument;
if (doc != null)
{
// 触发预注册的命令 "CadHive_ProcessWebImport"
doc.SendStringToExecute("CadHive_ProcessWebImport ", false, false, false);
}
// 6. 返回成功响应
byte[] buffer = Encoding.UTF8.GetBytes("{"status":"queued"}");
context.Response.OutputStream.Write(buffer, 0, buffer.Length);
context.Response.Close();
}
}
2.2 线程安全与命令执行
这是最容易踩坑的地方。AutoCAD 的数据库操作(如开启事务、修改图元)必须在主线程中进行。 HTTP Listener 运行在后台线程,直接操作 CAD 会导致崩溃( 错误)。
eNotMainThread
我的解决方案是:
后台线程接收数据,存入 静态类。使用
ImportContext 向 AutoCAD 命令行发送指令。AutoCAD 主线程接收到指令,触发
doc.SendStringToExecute,此时环境已安全。
[CommandMethod]
// myCommands.cs
[CommandMethod("CadHive_ProcessWebImport", CommandFlags.Modal)]
public void ProcessWebImport()
{
var doc = Application.DocumentManager.MdiActiveDocument;
var request = ImportContext.CurrentRequest; // 从上下文获取数据
if (request == null) return;
// 此时已在主线程,可以安全开启事务
using (doc.LockDocument()) // 锁定文档
using (Transaction tr = doc.TransactionManager.StartTransaction())
{
// 执行复杂的绘图逻辑:解析 Markdown,计算排版,绘制 MText 和 Table
ImportMarkdownLogic(doc, request.markdown, request.template);
tr.Commit();
}
// 清理上下文,防止重复执行
ImportContext.CurrentRequest = null;
}
3. 进阶功能:自动化排版引擎
打通通信只是第一步,核心价值在于**“数据 -> 图形”的转化能力**。
在本项目中,我实现了一个Markdown 解析与自动排版引擎。它不仅仅是简单的文字放置,而是实现了类似浏览器的渲染逻辑:
智能分栏:根据图框大小(A1/A2),自动计算列宽和列数。动态分页:当内容超过一张图纸时,自动复制图框,生成“设计说明-1”、“设计说明-2”。样式映射:将 Markdown 的 映射为 CAD 的不同字号,将
# 标题 渲染为 AutoCAD原生
| 表格 | 实体。避让算法:计算每个段落的
Table,确保文字与表格之间有精确的间距(如标题后紧跟正文,段落间距 1.5 倍行高)。
GeometricExtents
关于作者
资深 CAD/BIM 二次开发工程师
专注于 AutoCAD、Revit 开发及工程软件数字化解决方案。擅长 C# .NET、C++、Python 混合开发。
如果您有类似的CAD 自动化、Web 与 CAD 集成、AI 辅助设计开发需求,欢迎通过私信或以下方式联系我。
GitHub: https://github.com/zhuzhaoyun/md2cadEmail: dlutyaol@qq.com业务范围: AutoCAD 、BIM 软件、AI 工具或平台开发。
觉得有帮助?欢迎点赞、收藏、关注!