
简介本资源是一套开箱即用的SolidWorks二次开发C#模板工程面向机械设计工程师、CAD自动化开发者及具备基础C#编程能力的初学者旨在解决SolidWorks功能定制化门槛高、插件开发环境搭建复杂、COM接口调用不熟悉等实际问题。压缩包共99个文件涵盖18个核心C#源码.cs、2个Visual Studio解决方案.sln与项目文件.csproj、34个运行依赖DLL及5个资源文件.resx/.bmp完整复现了SwCSharpAddin1插件项目的标准目录结构——含事件处理EventHandling.cs、界面窗体Form1/XtraForm1、插件主类SwAddin.cs、工具栏图标与配置文件支持快速编译部署为COM Add-in。资源包大小10.24MB结构清晰、注释规范已为开发者预置SDK引用、事件注册、命令绑定与错误日志框架。目前已有730人学习下载可直接用于SolidWorks 2016–2022版本的插件开发实践显著缩短从零搭建到功能验证的周期。1. SolidWorks二次开发模板不是“写个宏就完事”而是搭好可复用、能交付、经得起工程验收的插件骨架你有没有遇到过这种场景客户提了个需求——“在装配体里批量给所有螺钉加防松标记”你吭哧吭哧写了300行VBA宏双击运行能跑通结果一交到产线同事手上对方点开就报错“找不到引用库”或者改了SolidWorks版本后直接白屏再一问原来宏里硬编码了D:\Projects\temp\mark.slddrw路径还依赖一个没打包的.dll更糟的是三个月后客户要加“按紧固力矩分级着色”功能你翻出原始代码发现变量命名全是a,b1,xx2连自己都看不懂逻辑在哪一层。这不是个别现象——大量SolidWorks现场开发卡在“能跑就行”的临界点缺的不是语法能力而是一套开箱即用、结构清晰、错误可控、升级有路的工程化起点。这个“SolidWorks二次开发模板”就是为此而生它不教你如何画螺栓而是给你一套已预置项目结构、自动注册机制、日志兜底、异常隔离、配置驱动的C#/.NET插件骨架。适合机械设计自动化推进组、PLM实施团队、以及想把个人脚本升级为部门级工具的资深工程师。它解决的不是“能不能做”而是“能不能稳定交付、能不能快速迭代、能不能让别人也维护”。2. 技术栈与工程结构为什么选.NET Framework 4.7.2 C# SwAddin NuGet包管理SolidWorks二次开发长期存在技术路线撕裂VBA轻量但难维护C SDK强大但编译链复杂Python通过COM调用又受限于GIL和部署环境。这个模板选择.NET Framework 4.7.2非.NET Core/.NET 5是经过产线实测验证的务实决策——SolidWorks 2018–2024所有主流版本均原生支持该框架且其COM互操作层SolidWorks.Interop.sldworks等P/Invoke封装成熟稳定无运行时兼容性黑匣子。更重要的是它天然支持Windows服务式插件SwAddin能实现菜单注入、命令响应、文档事件监听三位一体比宏更贴近原生体验。2.1 模板目录结构6大核心文件夹定义职责边界项目采用分层架构拒绝“所有代码塞进一个.cs文件”的反模式。解压后你会看到如下结构已剔除bin/obj等生成物SolidWorksAddInTemplate/ ├── AddIn/ # 插件主入口SwAddin继承类、注册/注销逻辑、全局事件总线 ├── Commands/ # 命令模块每个ICommand实现类对应一个菜单项如“批量标注” ├── Models/ # 数据模型与SolidWorks对象解耦的业务实体如BoltSpec、MarkRule ├── Services/ # 服务层封装SolidWorks API调用如DrawingService.CreateView、错误重试、事务包装 ├── Utils/ # 工具集通用扩展方法SldPartDoc.GetMassProperties()、路径解析、配置读取 └── Properties/ # 程序集信息、注册表键值、版本号关键影响安装路径和注册行为提示AddIn/SwAddIn.cs是整个插件的“心脏”它必须继承SolidWorks.Interop.sldworks.SwAddin并实现ConnectToSW()和DisconnectFromSW()。模板中已预置Application.SldWorks实例缓存、Document事件订阅模板、以及OnIdle()轮询钩子——这些不是可选项而是避免UI卡死、资源泄漏的刚需。2.2 核心依赖项NuGet包已锁定版本杜绝“本地能跑线上炸”模板通过packages.config明确定义以下依赖全部为官方NuGet源可获取包名版本作用是否必需SolidWorks.Interop.sldworks33.0.0.0SolidWorks主API互操作程序集✅ 必需SolidWorks.Interop.swconst33.0.0.0常量枚举swDocumentTypes_e等✅ 必需Microsoft.Extensions.Logging.Abstractions5.0.0轻量日志接口便于后期替换Serilog等⚠️ 推荐Newtonsoft.Json13.0.3配置文件序列化如rules.json⚠️ 推荐注意sldworks和swconst版本号33.0.0.0对应SolidWorks 2023 SP0。若你使用2022请手动降级至32.0.0.0需从SolidWorks安装目录api/redist复制对应DLL并更新引用。这是新手最易翻车的第一步——不要试图用高版本DLL兼容低版SolidWorks会触发System.Runtime.InteropServices.COMException且无有效堆栈。2.3 注册机制不靠regsvr32用注册表脚本InstallUtil双保险模板摒弃手工注册DLL的玄学操作。它提供两套注册方案开发调试期运行RegisterForDebug.bat内含regasm /codebase /tlb命令将插件注册到当前用户HKEY_CURRENT_USER\Software\SolidWorks\AddIns64下正式部署期使用InstallUtil.exe执行InstallUtil.exe /i SolidWorksAddInTemplate.dll自动写入HKEY_LOCAL_MACHINE支持多用户环境。关键参数说明regasm /codebase /tlb SolidWorksAddInTemplate.dll/codebase强制注册DLL绝对路径避免GAC冲突/tlb生成类型库.tlb文件供SolidWorks加载时解析COM接口若提示“无法注册类型”大概率是.NET Framework未正确安装或DLL平台目标x64/x86与SolidWorks位数不匹配SolidWorks 2018全为x64务必设为Platform Target: x64。3. 核心模块拆解从菜单点击到模型修改的完整链路我们以一个典型功能——“为当前零件添加自定义属性Custom Property”为例追踪从UI交互到SolidWorks底层操作的每一步。这不仅是功能演示更是理解模板设计哲学的关键切口。3.1 命令注册Commands/AddCustomPropertyCommand.cs—— 让菜单“活”起来public class AddCustomPropertyCommand : ICommand { public string Name AddCustomProperty; public string Title 添加自定义属性; public string Tooltip 为当前零件添加[设计者]、[审核日期]字段; public void OnCommand() { // 1. 获取当前活动文档安全检查 var doc SwAddIn.Instance.Application.ActiveDoc; if (doc null || doc.GetType() ! (int)swDocumentTypes_e.swDocPART) { MessageBox.Show(请先打开一个零件文件); return; } // 2. 构造业务参数解耦UI与逻辑 var props new Dictionarystring, string { [设计者] Environment.UserName, [审核日期] DateTime.Now.ToString(yyyy-MM-dd) }; // 3. 委托给服务层执行非阻塞UI线程 try { var service new CustomPropertyService(SwAddIn.Instance.Application); service.AddProperties(doc, props); MessageBox.Show(自定义属性添加成功); } catch (Exception ex) { // 4. 统一日志记录见Utils/Logger.cs SwAddIn.Instance.Logger.LogError(ex, AddCustomPropertyCommand.OnCommand failed); MessageBox.Show($操作失败{ex.Message}); } } }逻辑说明ICommand接口是模板定义的命令契约所有菜单项必须实现它确保统一生命周期管理SwAddIn.Instance.Application是单例持有的SolidWorks Application对象避免重复获取导致性能损耗CustomPropertyService被设计为无状态服务类可被多个命令复用符合单一职责原则异常捕获后调用Logger.LogError()而非裸抛保证错误可追溯日志默认输出到%APPDATA%\SolidWorksAddInTemplate\logs\。3.2 服务实现Services/CustomPropertyService.cs—— 封装SolidWorks API的“安全壳”public class CustomPropertyService { private readonly SldWorks _swApp; public CustomPropertyService(SldWorks swApp) { _swApp swApp ?? throw new ArgumentNullException(nameof(swApp)); } public void AddProperties(ModelDoc2 model, Dictionarystring, string properties) { // 关键使用Transaction确保原子性失败则回滚不残留半成品 using (var transaction new Transaction(_swApp)) { foreach (var kvp in properties) { // SolidWorks API要求属性名必须为ASCII值可UTF-8 var propName Encoding.ASCII.GetString(Encoding.ASCII.GetBytes(kvp.Key)); var propValue kvp.Value; // 调用底层API此处为简化实际含重试逻辑 var result model.Extension.SetCustomProperty3( propName, (int)swCustomInfoType_e.swCustomInfoText, propValue, (int)swCustomInfoOptions_e.swCustomInfoDeleteIfExists); if (result ! 1) // 返回1表示成功 { throw new InvalidOperationException($设置属性 {propName} 失败返回码: {result}); } } transaction.Commit(); // 显式提交事务 } } }参数说明model.Extension.SetCustomProperty3()是SolidWorks官方推荐的自定义属性设置方法替代已废弃的SetCustomProperty2第三个参数swCustomInfoOptions_e.swCustomInfoDeleteIfExists确保同名属性被覆盖而非追加避免脏数据Transaction类是模板自研的简易事务包装器非SolidWorks原生内部通过_swApp.CommandInProgress true/false模拟事务边界防止用户中途关闭文档导致状态不一致。3.3 配置驱动Utils/ConfigManager.cs—— 让规则脱离代码交给配置文件模板预置appsettings.json用于管理可变参数{ CustomPropertyRules: { AutoAddOnSave: true, RequiredFields: [设计者, 版本号, 校验人], DefaultValueMap: { 版本号: V1.0, 校验人: QA-Team } }, Logging: { Level: Information, MaxFileSizeKB: 10240 } }ConfigManager通过强类型绑定读取public static class ConfigManager { private static readonly IConfigurationRoot _config new ConfigurationBuilder() .SetBasePath(AppDomain.CurrentDomain.BaseDirectory) .AddJsonFile(appsettings.json, optional: false, reloadOnChange: true) .Build(); public static CustomPropertyConfig CustomProperty _config.GetSection(CustomPropertyRules).GetCustomPropertyConfig(); } public class CustomPropertyConfig { public bool AutoAddOnSave { get; set; } public Liststring RequiredFields { get; set; } new(); public Dictionarystring, string DefaultValueMap { get; set; } new(); }注意reloadOnChange: true使配置文件修改后无需重启SolidWorks即可生效需配合IOptionsMonitorT模式模板中已预留接入点。这是产线快速响应规则变更的核心能力。4. 常见问题排查那些让你加班到凌晨的“经典翻车现场”SolidWorks二次开发的调试环境极其特殊——它运行在SolidWorks主进程内IDE断点常失效错误信息常被吞掉。以下是模板用户高频反馈的5个真实问题附带血泪经验总结4.1 现象插件菜单显示为灰色不可点击原因AddIn/SwAddin.cs中ConnectToSW()方法未正确设置AddInEnabled true或ISwAddin.ConnectToSW()返回false未处理。解决检查ConnectToSW()末尾是否遗漏return true;若需条件启用如仅限特定SolidWorks版本必须显式返回true否则SolidWorks认为插件初始化失败而禁用菜单。4.2 现象调用ModelDoc2.Extension.SelectByID2()选中特征失败返回false原因SolidWorks坐标系与.NET坐标系Y轴方向相反传入的屏幕坐标未做转换或特征名称含空格/特殊字符未转义。解决使用模板提供的ScreenPointConverter.ToSolidWorksSpace()方法转换坐标特征名用Regex.Replace(name, [^a-zA-Z0-9_], _)清洗后再传入。4.3 现象插件安装后SolidWorks启动变慢甚至崩溃原因SwAddin.DisconnectFromSW()中未释放Document事件订阅如doc.OnSaveNotify OnSaveHandler导致内存泄漏或Dispose()未调用GC.SuppressFinalize(this)。解决模板SwAddin.cs已内置UnsubscribeAllEvents()方法在DisconnectFromSW()中强制调用所有事件处理器必须用注册-注销禁止匿名函数无法注销。4.4 现象中文路径下Assembly.LoadFrom()加载DLL失败报FileNotFoundException原因SolidWorks进程工作目录Working Directory默认为SolidWorks安装路径如C:\Program Files\SOLIDWORKS Corp\SOLIDWORKS非插件所在目录。解决改用Assembly.Load(File.ReadAllBytes(assemblyPath))绕过路径限制或在ConnectToSW()开头执行Directory.SetCurrentDirectory(AppDomain.CurrentDomain.BaseDirectory)重置工作目录。4.5 现象多线程调用SolidWorks API如后台导出PDF随机崩溃原因SolidWorks COM对象非线程安全所有API调用必须在主线程STA线程执行。解决模板Utils/ThreadHelper.cs提供InvokeOnMainThread(Action action)方法强制回调到UI线程ThreadHelper.InvokeOnMainThread(() { var pdfPath Path.Combine(tempDir, output.pdf); model.Extension.SaveAs(pdfPath, (int)swSaveAsOptions_e.swSaveAsOptions_Silent, ...); });5. 二次开发实战如何在30分钟内新增一个“BOM自动编号”功能现在我们动手改造模板添加一个真实产线需求“为装配体BOM中的每个零部件按层级深度自动编号如1.1, 1.2, 2.1.1”。这不是概念演示而是可立即投入使用的增量开发流程。5.1 步骤1定义命令入口5分钟在Commands/下新建AutoNumberBomCommand.cspublic class AutoNumberBomCommand : ICommand { public string Name AutoNumberBom; public string Title BOM自动编号; public string Tooltip 按装配层级为BOM项生成唯一编号; public void OnCommand() { var doc SwAddIn.Instance.Application.ActiveDoc; if (doc?.GetType() ! (int)swDocumentTypes_e.swDocASSEMBLY) { MessageBox.Show(请在装配体中使用此功能); return; } try { var service new BomNumberingService(SwAddIn.Instance.Application); var result service.GenerateNumbering((AssemblyDoc)doc); MessageBox.Show($已为{result.Count}个零部件编号\n示例{string.Join(, , result.Take(3))}); } catch (Exception ex) { SwAddIn.Instance.Logger.LogError(ex, AutoNumberBomCommand failed); MessageBox.Show($编号失败{ex.Message}); } } }关键动作ICommand实现类只需30行业务逻辑全委托给服务层保持命令层极度轻量。5.2 步骤2实现服务逻辑15分钟在Services/下新建BomNumberingService.cs核心是递归遍历装配体结构public class BomNumberingService { private readonly SldWorks _swApp; private int _counter 0; public BomNumberingService(SldWorks swApp) _swApp swApp; public Dictionarystring, string GenerateNumbering(AssemblyDoc assembly) { var numberingMap new Dictionarystring, string(); var rootComp assembly.GetRootComponent3(true); TraverseComponent(rootComp, , numberingMap); return numberingMap; } private void TraverseComponent(Component2 comp, string prefix, Dictionarystring, string map) { if (comp null) return; // 生成编号根组件为1子组件为1.1, 1.2... var number string.IsNullOrEmpty(prefix) ? (_counter).ToString() : ${prefix}.{_counter}; // 获取零部件路径唯一标识 var path comp.GetPathName(); if (!string.IsNullOrEmpty(path)) { map[path] number; } // 递归子装配体 var subAsm comp.GetModelDoc2() as AssemblyDoc; if (subAsm ! null) { var children subAsm.GetComponents(false); for (int i 0; i children.Length; i) { var child children[i] as Component2; TraverseComponent(child, number, map); // 传递当前编号作为前缀 } } } }逻辑说明TraverseComponent采用深度优先遍历确保编号顺序与BOM展开顺序一致使用Component2.GetPathName()获取绝对路径作为key避免同名零件冲突prefix参数实现层级编号拼接无需额外栈结构空间复杂度O(1)。5.3 步骤3注册到UI并测试10分钟打开AddIn/SwAddin.cs在CreateCommandManager()方法中添加_commandManager.RegisterCommand(new AutoNumberBomCommand());重新编译项目运行RegisterForDebug.bat启动SolidWorks → 打开任意装配体 → 查看“工具”菜单 → 点击“BOM自动编号”检查弹窗结果并验证SolidWorks任务窗格中BOM表格是否同步更新需配合IEdmBomTable接口此处为简化演示。提示若需持久化编号到自定义属性只需在TraverseComponent中追加var model comp.GetModelDoc2(); if (model ! null) model.Extension.SetCustomProperty3(BOM编号, (int)swCustomInfoType_e.swCustomInfoText, number, 0);从创建命令类、编写服务、到注册启用全程无需修改模板核心框架代码。这就是工程化模板的价值——新功能开发写业务逻辑注册命令其他一切由骨架兜底。从那以后我每次接到产线需求都强制走一遍“Commands→Services→注册”三步哪怕只是临时脚本也先搭好这个架子。因为我知道今天省下的10分钟会在三个月后某个深夜的紧急补丁里变成3小时的定位时间。希望帮到你。本文还有配套的精品资源点击获取