夜雨聆风学习资料网

ARTICLE · 1095296

实战|用 AI 写 CAD 插件:自动保存接管Ctrl+S(附源码 + 提示词)

实战|用 AI 写 CAD 插件:自动保存接管Ctrl+S(附源码 + 提示词)

点击蓝字,关注我们

这是《零基础 CAD 插件从 0 到 1》第 11 篇

今天应小伙伴的要求做一个自动保存的插件。

做设计的朋友,应该都有过一次心态崩盘的经历: 改图改到后半夜,正准备收尾保存,突然电脑死机、停电,或者 CAD 直接闪退。 等再打开,自带的自动保存只存了半小时前的版本,中间几个小时的活直接蒸发,找备份文件藏在 C 盘深处,找着了也大概率是损坏的。 辛辛苦苦大半天,一下回到解放前。

CAD 原生的自动保存,要么间隔太粗、要么文件难找、要么没有历史版本,关键时刻根本靠不住。 今天咱们用 AI 写一个真正省心的自动保存插件:后台定时自动保存,自动留存历史版本,一次设置好路径和间隔,所有图纸全局生效。不用再疯狂按 Ctrl+S,不用到处找备份,死机断电也能找回最新版本。

先看效果:一次设置,自动保存

看实际操作:

插件设置

历史版本位置

不用手动存,不用自己找。 你只管画图,保存的事交给插件。到点自动后台存,每次保存都留一个历史版本,出了问题直接去文件夹里挑时间点恢复,稳得很。

这个插件解决了什么问题?

针对设计师最怕的「丢图、白做」痛点,做了四个核心优化:

  1. 后台静默自动保存
    按设定的间隔自动执行保存,不打断画图、比自己按 Ctrl+S 还顺滑。
  2. 多版本历史留存
    每次自动保存都会备份一个独立版本,按时间戳命名,保留指定数量的历史文件。存错了、改崩了,随时回溯到任意时间的版本。
  3. 统一路径好管理
    备份文件统一存在你指定的文件夹,按图纸名称分类归档。不用再去 C 盘找隐藏目录,不用翻后缀为 sv$ 的文件,一目了然。
  4. 一次设置全局生效
    安装后设置一次保存间隔、是否开启备份、备份路径、保留版本数,以后打开任何 CAD 图纸都自动生效,不用每张图单独配置。

交互设计:一次设置,永久使用

完全轻量化设计,不用复杂操作,设置一次就再也不用管:

首次配置(仅做一次)

  1. 输入 AUTOSAVESETTINGS 回车,打开配置
  2. 设置保存间隔(推荐 5-10 分钟)、开启 / 关闭备份、备份文件夹路径、保留历史版本数
  3. 确认,插件自动开始后台运行

日常使用

全程无感,正常画图即可。 到点自动保存,自动备份版本;遇到闪退、断电,直接去备份文件夹找对应图纸的最新版本。

核心干货:给 AI 的精准提示词

还是那句话

用 AI 写插件写出来的功能不对,本质是需求没说细。AI 就像助理,你说清楚规则,它才能做准。下面是实测多轮、输出稳定能用的提示词模板,直接复制就能用:

角色设定:你是资深 CAD .NET 二次开发工程师,精通 C# 与 CAD 原生 API,面向全屋定制设计场景开发插件。

功能需求:开发一个「自动保存与历史版本备份」插件,具体要求:

命令名:AUTOSAVESETTINGS 

核心逻辑

:插件加载后后台静默运行,按设定间隔自动保存当前文档;支持自动备份历史版本,配置一次全局生效

配置功能
:通过命令调出配置,可设置保存间隔(分钟)、是否开启备份、备份文件路径、保留历史版本数量
备份规则
:开启备份后,每次自动保存时将当前图纸复制一份到备份目录,按「图纸名_年月日时分」格式命名;超过保留数量自动删除最早的版本
运行规则
:CAD 启动加载插件后自动生效,对当前活动窗口生效;保存时给出轻量命令行提示,不弹出窗口打断操作

环境:.NET Framework 4.8,AutoCAD 2021,引用 AcMgd、AcDbMgd;

输出要求:

给出完整可复制编译的代码

关键逻辑加中文注释

说明编译和加载方法

写提示词的核心原则

  1. 先定身份先让 AI 进入专业 CAD 开发的角色,避免用错 API、写出行外代码。

  2. 再划边界明确命令名、CAD 版本、运行环境,从根源减少兼容问题和报错。

  3. 讲清规则怎么保存、怎么注入、怎么设为当前,每一步规则都说死,不给 AI 自由发挥的空间。

  4. 固定格式要完整代码、要注释、要部署说明,都明确提出来,输出直接能用。

照着这个结构写,AI 输出代码的可用率至少提升 80%。

核心源码分享

下面是核心实现代码,基于 C# + CAD .NET API 编写,后台定时器驱动,带配置记忆与历史版本管理。

命令主逻辑:配置管理 + 定时保存 + 版本备份

using Autodesk.AutoCAD.ApplicationServices;using Autodesk.AutoCAD.Runtime;using System;using System.IO;using AcadApp = Autodesk.AutoCAD.ApplicationServices.Application;using Exception = System.Exception; namespace AutoSavePlugin{    public class AutoSaveManager : IExtensionApplication    {        private static DateTime _lastSaveTime = DateTime.MinValue;        private static bool _firstRunPromptShown = false;        internal static AutoSaveConfig Config;        internal static string ConfigPath;        internal static readonly string LogDir = Path.Combine(            Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData),            "AutoSavePlugin");        publicvoidInitialize()        {            try            {                ConfigPath = Path.Combine(LogDir, "config.xml");                bool firstRun = !File.Exists(ConfigPath);                Config = AutoSaveConfig.Load(ConfigPath);                if (firstRun) Config.Save(ConfigPath);                ApplyConfig();                Application.Idle += OnFirstIdle;                _lastSaveTime = DateTime.Now;            }            catch (Exception ex)            {                WriteLog("plugin_log.txt", $"初始化失败: {ex}");            }        }        publicvoidTerminate()        {            try            {                Application.Idle -= OnFirstIdle;                Application.Idle -= OnApplicationIdle;                Application.Idle -= ShowFirstRunHint;                if (Config != null && Config.DisableNativeSave)                {                    int restore = Config.OriginalSaveTime > 0 ? Config.OriginalSaveTime : 10;                    AcadApp.SetSystemVariable("SAVETIME", restore);                }            }            catch { }        }        privatevoidOnFirstIdle(object sender, EventArgs e)        {            Application.Idle -= OnFirstIdle;            Application.Idle += OnApplicationIdle;            Application.Idle += ShowFirstRunHint;        }        privatevoidShowFirstRunHint(object sender, EventArgs e)        {            if (_firstRunPromptShown) return;            _firstRunPromptShown = true;            Application.Idle -= ShowFirstRunHint;            var doc = AcadApp.DocumentManager.MdiActiveDocument;            doc?.Editor.WriteMessage(                    "\n[自动保存] 插件已加载。" +                    "自动保存覆盖所有打开的图纸。" +                    "输入 AUTOSAVESETTINGS 可调整间隔与备份策略。\n");        }        internalstaticvoidApplyConfig()        {            if (Config == null) return;            if (!Config.EnableAutoSave) return;            try { AcadApp.SetSystemVariable("ISAVEBAK", 0); } catch { }            try { AcadApp.SetSystemVariable("ISAVEPERCENT", 50); } catch { }            if (Config.DisableNativeSave)            {                try                {                    int current = Convert.ToInt32(AcadApp.GetSystemVariable("SAVETIME"));                    if (current > 0) Config.OriginalSaveTime = current;                    AcadApp.SetSystemVariable("SAVETIME", 0);                }                catch { }            }            else            {                try                {                    int restore = Config.OriginalSaveTime > 0 ? Config.OriginalSaveTime : 10;                    AcadApp.SetSystemVariable("SAVETIME", restore);                }                catch { }            }        }        privatevoidOnApplicationIdle(object sender, EventArgs e)        {            if (Config == null || !Config.EnableAutoSave) return;            if (DateTime.Now - _lastSaveTime < TimeSpan.FromMinutes(Config.IntervalMinutes))                return;            var doc = AcadApp.DocumentManager.MdiActiveDocument;            if (doc == null) return;            if (string.IsNullOrEmpty(doc.Name)) return;            PerformAutoSave(doc);            _lastSaveTime = DateTime.Now;        }        privatevoidPerformAutoSave(Document doc)        {            FileInfo fi;            try            {                fi = new FileInfo(doc.Name);                if (!fi.Exists) return;            }            catch { return; }            if (fi.IsReadOnly)            {                try                {                    using (doc.LockDocument())                        BackupManager.CreateHistoryBackup(doc.Name, Config);                }                catch { }                return;            }            try            {                using (doc.LockDocument())                    BackupManager.CreateHistoryBackup(doc.Name, Config);            }            catch (Exception ex)            {                WriteLog("plugin_log.txt", $"备份异常: {ex.Message}");            }            try            {                AcadApp.DocumentManager.ExecuteInCommandContextAsync(                    async (obj) =>                    {                        try                        {                            await doc.Editor.CommandAsync("_.QSAVE");                        }                        catch (Exception ex)                        {                            WriteLog("plugin_log.txt", $"QSAVE 失败: {ex.Message}");                        }                    },                    null);            }            catch (Exception ex)            {                WriteLog("plugin_log.txt", $"CommandContext 调用失败: {ex.Message}");            }        }        [CommandMethod("CADSAVESETTINGS")]        publicvoidShowSettings()        {            try            {                var window = new SettingsWindow();                AcadApp.ShowModelessWindow(AcadApp.MainWindow.Handle, window, false);            }            catch (Exception ex)            {                AcadApp.ShowAlertDialog("打开设置窗口失败: " + ex.Message);            }        }        internalstaticvoidWriteLog(string fileName, string message)        {            try            {                Directory.CreateDirectory(LogDir);                string path = Path.Combine(LogDir, fileName);                try                {                    var fi = new FileInfo(path);                    if (fi.Exists && fi.Length > 1024 * 1024)                        File.WriteAllText(path, "");                }                catch { }                File.AppendAllText(path,                    $"{DateTime.Now:yyyy-MM-dd HH:mm:ss.fff}{message}\r\n");            }            catch { }        }    }}

用 AI 开发插件的完整流程

这类后台工具型插件,用 AI 分步开发,上手最快:

  1. 需求拆解
    把「自动保存备份」拆成「定时驱动→执行保存→文件备份→配置管理」四个模块,逐个让 AI 实现,不要一次性丢完整需求。
  2. 分步验证
    先写定时器和保存逻辑,测准自动保存的时机;再加文件备份逻辑,测版本命名和清理;最后加配置读写,测全局生效。每一步跑通再往下,出问题好定位。
  3. 实测优化
    挂着插件画半天图,测试会不会卡顿、会不会打断命令、大图纸保存会不会出错;把遇到的问题丢给 AI,让它优化异常处理。
  4. 细节调整
    比如默认间隔、备份路径,都可以根据自己的习惯改,让 AI 直接调参数就行。

成品领取 & 下期预告

成品插件直接领

不想自己编译、调代码的朋友,关注公众号 「下班让AI教我做插件」,后台回复 「自动保存」,直接领取编译好的 DLL 插件文件,NETLOAD 加载或者是使用我写的dll插件加载工具箱。 完整工程源码拿到手就能二次修改。

下期预告

下一篇咱们继续深化标注提效工具,如果有想要的插件可以在评论区留言,我看看哪个留言最多就做哪个。

我是做插件的设计师,专注用 AI 提高 CAD 设计效率。关注我,下班一起做插件,把重复工作交给程序。

E

N

D

相关学习资料