实战干货】打破次元壁:如何实现 Web 端与 AutoCAD 桌面端的双向通信与自动化绘图

阿里云教程3个月前发布
19 0 0

前言

在工程建设与制造业数字化转型的浪潮中,我们经常面临一个架构难题:业务流在 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
搭建轻量级服务。监听本地特定端口(如
19090
)。处理跨域(CORS)问题,允许浏览器直接调用。
线程同步机制:将 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
静态类。使用
doc.SendStringToExecute
向 AutoCAD 命令行发送指令。AutoCAD 主线程接收到指令,触发
[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
实体。避让算法:计算每个段落的
GeometricExtents
,确保文字与表格之间有精确的间距(如标题后紧跟正文,段落间距 1.5 倍行高)。



关于作者

资深 CAD/BIM 二次开发工程师
专注于 AutoCAD、Revit 开发及工程软件数字化解决方案。擅长 C# .NET、C++、Python 混合开发。

如果您有类似的CAD 自动化、Web 与 CAD 集成、AI 辅助设计开发需求,欢迎通过私信或以下方式联系我。

GitHub: https://github.com/zhuzhaoyun/md2cadEmail: dlutyaol@qq.com业务范围: AutoCAD 、BIM 软件、AI 工具或平台开发。


觉得有帮助?欢迎点赞、收藏、关注!

© 版权声明

相关文章

暂无评论

none
暂无评论...