简介:本资源是一套面向机械设计工程师、CAD开发人员及高校相关专业学习者的SolidWorks二次开发入门与进阶实战素材包,聚焦API编程、COM接口调用与插件定制等核心能力培养,助力用户突破标准化设计瓶颈,实现参数化建模、ERP数据对接、自动化仿真验证等企业级应用。压缩包为RAR格式,大小54.08MB,虽未提供具体文件列表,但结合描述可知内容覆盖API基础类库说明、C#与VBA双语言示例代码、Visual Studio开发环境配置指南、典型应用场景(如特征库构建、工程图批量生成)的完整实现逻辑及错误处理与性能优化实践要点。已有585人学习下载,资源结构兼顾理论框架与可运行代码片段,特别适合从零起步掌握SolidWorks定制开发,并快速迁移到实际项目中的中初级开发者。
1. SolidWorks二次开发不是“写个宏就完事”,而是让设计系统听你指挥的工程实践
很多刚接触SolidWorks二次开发的工程师,第一反应是打开VBA编辑器录个宏、改两行代码,以为这就叫“开发”。但真实场景远比这复杂:某汽车零部件厂用C#插件自动校验200+个装配干涉项,把人工检查从4小时压缩到17秒;某风电企业将SolidWorks与内部PLM系统打通,每次保存零件时自动触发BOM生成、版本归档和审批流推送;还有团队用COM接口批量重建焊件结构树,解决GB型材库导入后特征丢失问题。这些不是脚本级操作,而是嵌入设计流程底层的系统级集成。SolidWorks二次开发的本质,是通过API接管软件核心对象生命周期——从Document创建、Feature重建、Sketch几何约束求解,到Drawing视图投影、Configuration切换、PropertyManagerPage交互响应。它要求开发者既懂机械设计逻辑(比如特征建模顺序对重建失败的影响),又熟悉COM互操作机制(如SwApp对象的线程模型限制),还要处理SolidWorks主进程的稳定性边界(例如避免在OnIdle事件中执行耗时计算)。适合两类人:一是有3年以上SolidWorks实操经验、能准确描述“为什么这个Feature重建会失败”的资深设计师;二是熟悉.NET或C++内存管理、能看懂IDispatch接口定义的开发工程师。两者缺一不可。
2. COM接口调用不是调用普通DLL:理解ISwModel与SwApp的生命周期绑定关系
2.1 SolidWorks API的COM本质决定了开发语言选择边界
SolidWorks API并非标准.NET类库,而是基于Windows COM组件模型暴露的类型库(swconst.tlb、swassembly.tlb等)。这意味着所有调用都必须经过COM互操作层(COM Interop),其核心约束直接决定技术选型:
- VBA:仅限于宏录制与简单逻辑,因运行在SolidWorks进程内,无需跨进程通信,但无法引用外部.NET库,且调试能力极弱;
- C#/.NET Framework:主流选择,需引用
SolidWorks.Interop.sldworks.dll等互操作程序集,该DLL由tlbimp.exe生成,封装了COM接口的托管包装器; - C++/ATL:性能最优,可直接调用IUnknown接口,但需手动管理引用计数、处理HRESULT返回值,且VS项目配置复杂;
- VB.NET:语法友好但已逐步被C#替代,社区支持度下降。
提示:SolidWorks 2020及以后版本默认禁用.NET Core/.NET 5+,因COM互操作层依赖.NET Framework 4.7.2+的特定实现。若强行使用.NET 6+,需通过
Microsoft.Win32.RegistrationServices注册类型库,且部分接口(如ISwDrawing::CreateDrawViewFromModelView3)会抛出InvalidCastException。
2.2 SwApp对象获取是所有开发的起点,但极易踩坑
获取SolidWorks主应用程序对象(SldWorks)看似简单,实则暗藏陷阱。以下代码是常见错误写法:
// ❌ 错误:未检查SolidWorks是否已运行,且未处理COM异常 SldWorks swApp = new SldWorks(); ModelDoc2 model = swApp.ActiveDoc as ModelDoc2;正确做法必须包含三重校验:
// ✅ 正确:显式获取、空值检查、异常捕获 SldWorks swApp = null; try { // 尝试获取已运行实例(CLSID: {83A33D31-27C5-11CE-BFD4-00400513BB57}) swApp = (SldWorks)Marshal.GetActiveObject("SldWorks.Application"); } catch (COMException ex) when (ex.ErrorCode == unchecked((int)0x800401E3)) { // CLASS_NOT_AVAILABLE:SolidWorks未启动 MessageBox.Show("请先启动SolidWorks"); return; } catch (COMException ex) when (ex.ErrorCode == unchecked((int)0x800401E4)) { // OPERATION_UNAVAILABLE:权限不足(如以管理员身份运行VS但SolidWorks非管理员) MessageBox.Show("请确保SolidWorks与开发环境运行权限一致"); return; } // 检查是否获取成功且文档已打开 if (swApp == null || swApp.ActiveDoc == null) { MessageBox.Show("未检测到活动文档,请打开一个零件/装配体/工程图"); return; } ModelDoc2 model = swApp.ActiveDoc; // ⚠️ 关键:必须检查model类型,避免在Drawing文档上调用Part特有方法 if (model.GetType() != typeof(PartDoc)) { MessageBox.Show($"当前文档类型为{model.GetType().Name},本插件仅支持零件文档"); return; }2.2.1 SwApp对象的线程模型限制:为什么不能在后台线程调用API
SolidWorks API强制要求所有调用必须在STA(Single-Threaded Apartment)线程中执行。若在Task.Run或ThreadPool线程中调用swApp.NewDocument2,会立即抛出COMException(错误码0x8001010E,RPC_E_WRONG_THREAD)。解决方案只有两种:
方案1(推荐):使用
Control.Invoke委托到UI线程(WinForms/WPF)private void OnButtonClick(object sender, EventArgs e) { // 在UI线程中调用 var result = swApp.Invoke(new Func<bool>(() => { try { ModelDoc2 newPart = swApp.NewDocument2("C:\\Program Files\\SOLIDWORKS Corp\\SOLIDWORKS\\templates\\part.prtdot", (int)swDocumentTypes_e.swDocPART, 0, 0); return newPart != null; } catch (Exception ex) { MessageBox.Show($"创建失败:{ex.Message}"); return false; } })); }方案2:为后台任务显式创建STA线程(适用于长时间运算)
Thread workerThread = new Thread(() => { // 设置线程为STA Thread.CurrentThread.SetApartmentState(ApartmentState.STA); try { // 在此线程中获取SwApp并执行操作 SldWorks swApp = (SldWorks)Marshal.GetActiveObject("SldWorks.Application"); // ... 执行耗时操作 } catch (COMException ex) { // 处理COM异常 } }); workerThread.Start();
2.2.2 ISwModel接口的隐式释放风险:为什么Feature重建后模型变空白
ModelDoc2对象(即ISwModel)在.NET中受GC管理,但其底层COM引用计数由SolidWorks进程控制。常见错误是:在方法中创建局部ModelDoc2变量,方法结束时GC回收导致COM引用计数减1,若此时SolidWorks窗口未激活,可能触发模型卸载。验证方式:调用model.Extension.SelectByID2("Feature1", "BODYFEATURE", 0, 0, 0, true, 0, null, 0)后立即model.GraphicsRedraw2(),若界面无响应,大概率是对象提前释放。
安全写法:将ModelDoc2声明为窗体级字段,并在窗体关闭时显式释放:
public partial class MyPluginForm : Form { private ModelDoc2 _currentModel; // 窗体级持有引用 public void LoadActiveModel() { _currentModel = swApp.ActiveDoc; if (_currentModel == null) throw new InvalidOperationException("无活动文档"); } protected override void OnFormClosed(FormClosedEventArgs e) { // 显式释放COM对象,避免内存泄漏 if (_currentModel != null) { Marshal.ReleaseComObject(_currentModel); _currentModel = null; } base.OnFormClosed(e); } }3. 从VBA宏到C#插件:构建可部署的SolidWorks Add-in工程
3.1 Visual Studio项目配置的关键参数设置
新建Class Library项目后,必须调整以下五项配置,否则编译通过但运行时崩溃:
| 配置项 | 正确值 | 错误后果 |
|---|---|---|
| 目标框架 | .NET Framework 4.7.2(SolidWorks 2019+)或4.6.1(2017) | .NET Core导致System.Runtime.InteropServices.COMException |
| 平台目标 | x64(SolidWorks 64位)或x86(32位) | 架构不匹配引发BadImageFormatException |
| 注册COM互操作 | 勾选(Project Properties → Build → Register for COM interop) | 插件无法被SolidWorks识别 |
| 输出路径 | C:\Program Files\SOLIDWORKS Corp\SOLIDWORKS\lang\chinese-simplified\(中文版) | 插件菜单不显示 |
| 延迟签名 | 取消勾选(否则GAC注册失败) | RegAsm报错“无法注册类型” |
注意:SolidWorks 2023开始要求插件必须签名。若未配置证书,安装时会提示“无法验证发布者”。解决方案是在项目属性→签名页勾选“为ClickOnce清单签名”,并指定.pfx证书文件。
3.2 实现Add-in入口:ISwAddin接口的三个必需方法
SolidWorks插件必须实现SwAddin接口(SolidWorks.Interop.sldworks.ISwAddin),其三个方法构成插件生命周期:
public class MySolidWorksAddin : SwAddin { private SldWorks _swApp; private CommandGroup _cmdGroup; // ✅ ConnectToSW:插件加载时调用,必须在此获取SwApp并注册命令 public bool ConnectToSW(object ThisSW, int cookie) { _swApp = (SldWorks)ThisSW; _cookie = cookie; // 创建自定义命令组(工具栏) _cmdGroup = _swApp.CreateCommandGroup2( 1, // ID "我的插件", // 标题 "MyPlugin", // 工具提示 -1, // 图标索引(-1表示内置图标) false, // 是否显示在菜单 ref _cookie); // 添加命令项(按钮) _cmdGroup.AddCommandItem2( "生成标准件", // 名称 1, // 命令ID "icons\\bolt.ico", // 图标路径(相对插件DLL目录) "生成螺栓", // 工具提示 "点击生成ISO标准螺栓", // 状态栏文本 (int)swCommands_e.swCommands_Custom, // 命令类型 0, // 用户数据 true); // 启用 // 注册命令回调 _cmdGroup.CommandOpen += OnCommandOpen; return true; } // ✅ DisconnectFromSW:插件卸载时调用,必须释放所有COM对象 public bool DisconnectFromSW() { if (_cmdGroup != null) { Marshal.ReleaseComObject(_cmdGroup); _cmdGroup = null; } if (_swApp != null) { Marshal.ReleaseComObject(_swApp); _swApp = null; } return true; } // ✅ GetAddInInfo:返回插件元信息,SolidWorks据此显示名称和描述 public void GetAddInInfo(ref string Title, ref string Author, ref string Description, ref string Version) { Title = "我的SolidWorks插件"; Author = "Your Company"; Description = "用于自动化标准件生成的插件"; Version = "1.0.0"; } // 命令回调处理 private void OnCommandOpen(int CommandID) { if (_swApp.ActiveDoc is PartDoc part) { // 执行具体逻辑 CreateBolt(part); } } }3.2.1 注册表项配置:让SolidWorks在启动时加载你的插件
仅编译DLL不够,必须向Windows注册表写入插件信息。手动操作易出错,推荐使用RegAsm.exe工具:
# 在Visual Studio Developer Command Prompt中执行 cd /d "C:\YourPluginPath" "C:\Windows\Microsoft.NET\Framework64\v4.0.30319\RegAsm.exe" MyPlugin.dll /tlb /codebase该命令生成.tlb类型库并写入注册表HKEY_LOCAL_MACHINE\SOFTWARE\SOLIDWORKS\AddIns\{GUID},其中关键值:
Description:插件描述(显示在工具→插件列表)LoadAtStartup:DWORD=1(启动时自动加载)Title:插件名称(显示在菜单)
提示:若插件在SolidWorks中显示为灰色不可用,检查
LoadAtStartup值是否为1,且注册表路径中的GUID必须与项目AssemblyInfo.cs中[Guid("xxx")]一致。
3.3 调试技巧:如何在SolidWorks进程中实时断点调试
VS默认无法附加到SolidWorks进程,需手动配置:
- 启用本机代码调试:项目属性→调试→勾选“启用本机代码调试”
- 附加到进程:调试→附加到进程→选择
SLDWORKS.exe(注意:必须是当前打开SolidWorks文档的进程,而非多个同名进程) - 设置断点:在
ConnectToSW或命令回调方法中设断点 - 触发调试:在SolidWorks中点击插件按钮,VS自动中断
常见调试失败原因:
- VS与SolidWorks运行权限不一致(一个管理员一个标准用户)
- .NET Framework版本不匹配(VS用4.8,SolidWorks用4.7.2)
- 插件DLL路径含中文字符(注册表写入失败)
4. 特征自动化实战:用C#批量创建GB/T 1167-1996螺纹孔
4.1 分析GB螺纹孔建模逻辑:为什么不能直接调用InsertHoleWizard
GB/T 1167-1996规定螺纹孔需包含:沉头孔(Counterbore)、螺纹(Thread)、倒角(Chamfer)三特征,且尺寸严格关联。若用FeatureManager::FeatureHoleWzd,SolidWorks Hole Wizard默认生成ISO标准,无法精确控制GB参数(如沉头深度=1.5×螺纹大径)。必须用底层API逐特征构建:
| 特征类型 | 关键参数 | API调用方式 |
|---|---|---|
| 沉头孔 | 直径=螺纹大径+2mm,深度=1.5×大径 | FeatureManager::CreateCircle2+FeatureManager::FeatureCutEx2 |
| 螺纹 | 类型=Internal,规格=GB/T 193 | FeatureManager::FeatureThread(需先创建圆柱面) |
| 倒角 | 距离=0.5mm,角度=45° | FeatureManager::FeatureChamfer2 |
4.2 完整代码:创建M6×1.0螺纹孔的可复用方法
/// <summary> /// 在指定面上创建GB/T 1167-1996螺纹孔 /// </summary> /// <param name="model">当前模型</param> /// <param name="face">目标面(必须为平面)</param> /// <param name="centerX">孔中心X坐标(模型坐标系)</param> /// <param name="centerY">孔中心Y坐标</param> /// <param name="threadSize">螺纹规格,如"M6"</param> public static bool CreateGBT1167ThreadHole(ModelDoc2 model, Face2 face, double centerX, double centerY, string threadSize) { FeatureManager featMgr = model.FeatureManager; SelectionMgr selMgr = model.SelectionManager; // Step 1: 获取螺纹参数(简化版,实际应查GB表) double majorDiameter = threadSize switch { "M6" => 6.0, "M8" => 8.0, "M10" => 10.0, _ => throw new ArgumentException("不支持的螺纹规格") }; // Step 2: 创建沉头孔草图 SketchManager sketchMgr = model.CreateDrawnSketch2(face); sketchMgr.CreateCircle(centerX, centerY, 0, centerX + majorDiameter/2 + 1.0, centerY, 0); // 沉头直径 = 大径+2mm sketchMgr.CreateCircle(centerX, centerY, 0, centerX + majorDiameter/2, centerY, 0); // 螺纹底孔直径 = 大径 // Step 3: 拉伸切除沉头孔(深度=1.5×大径) object[] bodies = featMgr.FeatureCutEx2( true, // 薄壁 false, // 保持相交 false, // 合并实体 (int)swEndCondition_e.swEndCondUpToSurface, // 终止条件 0, // 深度 0, // 拔模角度 0, // 拔模方向 0, // 起始偏移 0, // 终止偏移 0, // 薄壁厚度 0, // 薄壁方向 0, // 薄壁拔模 0, // 薄壁拔模方向 0, // 薄壁起始偏移 0, // 薄壁终止偏移 0, // 薄壁拔模角度 0, // 薄壁拔模方向 0, // 薄壁起始偏移 0, // 薄壁终止偏移 0, // 薄壁拔模角度 0, // 薄壁拔模方向 0, // 薄壁起始偏移 0, // 薄壁终止偏移 0, // 薄壁拔模角度 0, // 薄壁拔模方向 0, // 薄壁起始偏移 0, // 薄壁终止偏移 0, // 薄壁拔模角度 0, // 薄壁拔模方向 0, // 薄壁起始偏移 0, // 薄壁终止偏移 0, // 薄壁拔模角度 0, // 薄壁拔模方向 0, // 薄壁起始偏移 0, // 薄壁终止偏移 0, // 薄壁拔模角度 0, // 薄壁拔模方向 0, // 薄壁起始偏移 0, // 薄壁终止偏移 0, // 薄壁拔模角度 0, // 薄壁拔模方向 0, // 薄壁起始偏移 0, // 薄壁终止偏移 0, // 薄壁拔模角度 0, // 薄壁拔模方向 0, // 薄壁起始偏移 0, // 薄壁终止偏移 0, // 薄壁拔模角度 0, // 薄壁拔模方向 0, // 薄壁起始偏移 0, // 薄壁终止偏移 0, // 薄壁拔模角度 0, // 薄壁拔模方向 0, // 薄壁起始偏移 ......## 1. SolidWorks二次开发不是“写个宏就完事”,而是让设计系统听你指挥的工程实践 很多刚接触SolidWorks二次开发的工程师,第一反应是打开VBA编辑器录个宏、改两行代码,以为这就叫“开发”。但真实场景远比这复杂:某汽车零部件厂用C#插件自动校验200+个装配干涉项,把人工检查从4小时压缩到17秒;某风电企业将SolidWorks与内部PLM系统打通,每次保存零件时自动触发BOM生成、版本归档和审批流推送;还有团队用COM接口批量重建焊件结构树,解决GB型材库导入后特征丢失问题。这些不是脚本级操作,而是嵌入设计流程底层的系统级集成。SolidWorks二次开发的本质,是通过API接管软件核心对象生命周期——从Document创建、Feature重建、Sketch几何约束求解,到Drawing视图投影、Configuration切换、PropertyManagerPage交互响应。它要求开发者既懂机械设计逻辑(比如特征建模顺序对重建失败的影响),又熟悉COM互操作机制(如SwApp对象的线程模型限制),还要处理SolidWorks主进程的稳定性边界(例如避免在OnIdle事件中执行耗时计算)。适合两类人:一是有3年以上SolidWorks实操经验、能准确描述“为什么这个Feature重建会失败”的资深设计师;二是熟悉.NET或C++内存管理、能看懂IDispatch接口定义的开发工程师。两者缺一不可。 ## 2. COM接口调用不是调用普通DLL:理解ISwModel与SwApp的生命周期绑定关系 ### 2.1 SolidWorks API的COM本质决定了开发语言选择边界 SolidWorks API并非标准.NET类库,而是基于Windows COM组件模型暴露的类型库(swconst.tlb、swassembly.tlb等)。这意味着所有调用都必须经过COM互操作层(COM Interop),其核心约束直接决定技术选型: - **VBA**:仅限于宏录制与简单逻辑,因运行在SolidWorks进程内,无需跨进程通信,但无法引用外部.NET库,且调试能力极弱; - **C#/.NET Framework**:主流选择,需引用`SolidWorks.Interop.sldworks.dll`等互操作程序集,该DLL由tlbimp.exe生成,封装了COM接口的托管包装器; - **C++/ATL**:性能最优,可直接调用IUnknown接口,但需手动管理引用计数、处理HRESULT返回值,且VS项目配置复杂; - **VB.NET**:语法友好但已逐步被C#替代,社区支持度下降。 > 提示:SolidWorks 2020及以后版本默认禁用.NET Core/.NET 5+,因COM互操作层依赖.NET Framework 4.7.2+的特定实现。若强行使用.NET 6+,需通过`Microsoft.Win32.RegistrationServices`注册类型库,且部分接口(如`ISwDrawing::CreateDrawViewFromModelView3`)会抛出`InvalidCastException`。 ### 2.2 SwApp对象获取是所有开发的起点,但极易踩坑 获取SolidWorks主应用程序对象(`SldWorks`)看似简单,实则暗藏陷阱。以下代码是常见错误写法: ```csharp // ❌ 错误:未检查SolidWorks是否已运行,且未处理COM异常 SldWorks swApp = new SldWorks(); ModelDoc2 model = swApp.ActiveDoc as ModelDoc2;正确做法必须包含三重校验:
// ✅ 正确:显式获取、空值检查、异常捕获 SldWorks swApp = null; try { // 尝试获取已运行实例(CLSID: {83A33D31-27C5-11CE-BFD4-00400513BB57}) swApp = (SldWorks)Marshal.GetActiveObject("SldWorks.Application"); } catch (COMException ex) when (ex.ErrorCode == unchecked((int)0x800401E3)) { // CLASS_NOT_AVAILABLE:SolidWorks未启动 MessageBox.Show("请先启动SolidWorks"); return; } catch (COMException ex) when (ex.ErrorCode == unchecked((int)0x800401E4)) { // OPERATION_UNAVAILABLE:权限不足(如以管理员身份运行VS但SolidWorks非管理员) MessageBox.Show("请确保SolidWorks与开发环境运行权限一致"); return; } // 检查是否获取成功且文档已打开 if (swApp == null || swApp.ActiveDoc == null) { MessageBox.Show("未检测到活动文档,请打开一个零件/装配体/工程图"); return; } ModelDoc2 model = swApp.ActiveDoc; // ⚠️ 关键:必须检查model类型,避免在Drawing文档上调用Part特有方法 if (model.GetType() != typeof(PartDoc)) { MessageBox.Show($"当前文档类型为{model.GetType().Name},本插件仅支持零件文档"); return; }2.2.1 SwApp对象的线程模型限制:为什么不能在后台线程调用API
SolidWorks API强制要求所有调用必须在STA(Single-Threaded Apartment)线程中执行。若在Task.Run或ThreadPool线程中调用swApp.NewDocument2,会立即抛出COMException(错误码0x8001010E,RPC_E_WRONG_THREAD)。解决方案只有两种:
方案1(推荐):使用
Control.Invoke委托到UI线程(WinForms/WPF)private void OnButtonClick(object sender, EventArgs e) { // 在UI线程中调用 var result = swApp.Invoke(new Func<bool>(() => { try { ModelDoc2 newPart = swApp.NewDocument2("C:\\Program Files\\SOLIDWORKS Corp\\SOLIDWORKS\\templates\\part.prtdot", (int)swDocumentTypes_e.swDocPART, 0, 0); return newPart != null; } catch (Exception ex) { MessageBox.Show($"创建失败:{ex.Message}"); return false; } })); }方案2:为后台任务显式创建STA线程(适用于长时间运算)
Thread workerThread = new Thread(() => { // 设置线程为STA Thread.CurrentThread.SetApartmentState(ApartmentState.STA); try { // 在此线程中获取SwApp并执行操作 SldWorks swApp = (SldWorks)Marshal.GetActiveObject("SldWorks.Application"); // ... 执行耗时操作 } catch (COMException ex) { // 处理COM异常 } }); workerThread.Start();
2.2.2 ISwModel接口的隐式释放风险:为什么Feature重建后模型变空白
ModelDoc2对象(即ISwModel)在.NET中受GC管理,但其底层COM引用计数由SolidWorks进程控制。常见错误是:在方法中创建局部ModelDoc2变量,方法结束时GC回收导致COM引用计数减1,若此时SolidWorks窗口未激活,可能触发模型卸载。验证方式:调用model.Extension.SelectByID2("Feature1", "BODYFEATURE", 0, 0, 0, true, 0, null, 0)后立即model.GraphicsRedraw2(),若界面无响应,大概率是对象提前释放。
安全写法:将ModelDoc2声明为窗体级字段,并在窗体关闭时显式释放:
public partial class MyPluginForm : Form { private ModelDoc2 _currentModel; // 窗体级持有引用 public void LoadActiveModel() { _currentModel = swApp.ActiveDoc; if (_currentModel == null) throw new InvalidOperationException("无活动文档"); } protected override void OnFormClosed(FormClosedEventArgs e) { // 显式释放COM对象,避免内存泄漏 if (_currentModel != null) { Marshal.ReleaseComObject(_currentModel); _currentModel = null; } base.OnFormClosed(e); } }3. 从VBA宏到C#插件:构建可部署的SolidWorks Add-in工程
3.1 Visual Studio项目配置的关键参数设置
新建Class Library项目后,必须调整以下五项配置,否则编译通过但运行时崩溃:
| 配置项 | 正确值 | 错误后果 |
|---|---|---|
| 目标框架 | .NET Framework 4.7.2(SolidWorks 2019+)或4.6.1(2017) | .NET Core导致System.Runtime.InteropServices.COMException |
| 平台目标 | x64(SolidWorks 64位)或x86(32位) | 架构不匹配引发BadImageFormatException |
| 注册COM互操作 | 勾选(Project Properties → Build → Register for COM interop) | 插件无法被SolidWorks识别 |
| 输出路径 | C:\Program Files\SOLIDWORKS Corp\SOLIDWORKS\lang\chinese-simplified\(中文版) | 插件菜单不显示 |
| 延迟签名 | 取消勾选(否则GAC注册失败) | RegAsm报错“无法注册类型” |
注意:SolidWorks 2023开始要求插件必须签名。若未配置证书,安装时会提示“无法验证发布者”。解决方案是在项目属性→签名页勾选“为ClickOnce清单签名”,并指定.pfx证书文件。
3.2 实现Add-in入口:ISwAddin接口的三个必需方法
SolidWorks插件必须实现SwAddin接口(SolidWorks.Interop.sldworks.ISwAddin),其三个方法构成插件生命周期:
public class MySolidWorksAddin : SwAddin { private SldWorks _swApp; private CommandGroup _cmdGroup; // ✅ ConnectToSW:插件加载时调用,必须在此获取SwApp并注册命令 public bool ConnectToSW(object ThisSW, int cookie) { _swApp = (SldWorks)ThisSW; _cookie = cookie; // 创建自定义命令组(工具栏) _cmdGroup = _swApp.CreateCommandGroup2( 1, // ID "我的插件", // 标题 "MyPlugin", // 工具提示 -1, // 图标索引(-1表示内置图标) false, // 是否显示在菜单 ref _cookie); // 添加命令项(按钮) _cmdGroup.AddCommandItem2( "生成标准件", // 名称 1, // 命令ID "icons\\bolt.ico", // 图标路径(相对插件DLL目录) "生成螺栓", // 工具提示 "点击生成ISO标准螺栓", // 状态栏文本 (int)swCommands_e.swCommands_Custom, // 命令类型 0, // 用户数据 true); // 启用 // 注册命令回调 _cmdGroup.CommandOpen += OnCommandOpen; return true; } // ✅ DisconnectFromSW:插件卸载时调用,必须释放所有COM对象 public bool DisconnectFromSW() { if (_cmdGroup != null) { Marshal.ReleaseComObject(_cmdGroup); _cmdGroup = null; } if (_swApp != null) { Marshal.ReleaseComObject(_swApp); _swApp = null; } return true; } // ✅ GetAddInInfo:返回插件元信息,SolidWorks据此显示名称和描述 public void GetAddInInfo(ref string Title, ref string Author, ref string Description, ref string Version) { Title = "我的SolidWorks插件"; Author = "Your Company"; Description = "用于自动化标准件生成的插件"; Version = "1.0.0"; } // 命令回调处理 private void OnCommandOpen(int CommandID) { if (_swApp.ActiveDoc is PartDoc part) { // 执行具体逻辑 CreateBolt(part); } } }3.2.1 注册表项配置:让SolidWorks在启动时加载你的插件
仅编译DLL不够,必须向Windows注册表写入插件信息。手动操作易出错,推荐使用RegAsm.exe工具:
# 在Visual Studio Developer Command Prompt中执行 cd /d "C:\YourPluginPath" "C:\Windows\Microsoft.NET\Framework64\v4.0.30319\RegAsm.exe" MyPlugin.dll /tlb /codebase该命令生成.tlb类型库并写入注册表HKEY_LOCAL_MACHINE\SOFTWARE\SOLIDWORKS\AddIns\{GUID},其中关键值:
Description:插件描述(显示在工具→插件列表)LoadAtStartup:DWORD=1(启动时自动加载)Title:插件名称(显示在菜单)
提示:若插件在SolidWorks中显示为灰色不可用,检查
LoadAtStartup值是否为1,且注册表路径中的GUID必须与项目AssemblyInfo.cs中[Guid("xxx")]一致。
3.3 调试技巧:如何在SolidWorks进程中实时断点调试
VS默认无法附加到SolidWorks进程,需手动配置:
- 启用本机代码调试:项目属性→调试→勾选“启用本机代码调试”
- 附加到进程:调试→附加到进程→选择
SLDWORKS.exe(注意:必须是当前打开SolidWorks文档的进程,而非多个同名进程) - 设置断点:在
ConnectToSW或命令回调方法中设断点 - 触发调试:在SolidWorks中点击插件按钮,VS自动中断
常见调试失败原因:
- VS与SolidWorks运行权限不一致(一个管理员一个标准用户)
- .NET Framework版本不匹配(VS用4.8,SolidWorks用4.7.2)
- 插件DLL路径含中文字符(注册表写入失败)
4. 特征自动化实战:用C#批量创建GB/T 1167-1996螺纹孔
4.1 分析GB螺纹孔建模逻辑:为什么不能直接调用InsertHoleWizard
GB/T 1167-1996规定螺纹孔需包含:沉头孔(Counterbore)、螺纹(Thread)、倒角(Chamfer)三特征,且尺寸严格关联。若用FeatureManager::FeatureHoleWzd,SolidWorks Hole Wizard默认生成ISO标准,无法精确控制GB参数(如沉头深度=1.5×螺纹大径)。必须用底层API逐特征构建:
| 特征类型 | 关键参数 | API调用方式 |
|---|---|---|
| 沉头孔 | 直径=螺纹大径+2mm,深度=1.5×大径 | FeatureManager::CreateCircle2+FeatureManager::FeatureCutEx2 |
| 螺纹 | 类型=Internal,规格=GB/T 193 | FeatureManager::FeatureThread(需先创建圆柱面) |
| 倒角 | 距离=0.5mm,角度=45° | FeatureManager::FeatureChamfer2 |
4.2 完整代码:创建M6×1.0螺纹孔的可复用方法
/// <summary> /// 在指定面上创建GB/T 1167-1996螺纹孔 /// </summary> /// <param name="model">当前模型</param> /// <param name="face">目标面(必须为平面)</param> /// <param name="centerX">孔中心X坐标(模型坐标系)</param> /// <param name="centerY">孔中心Y坐标</param> /// <param name="threadSize">螺纹规格,如"M6"</param> public static bool CreateGBT1167ThreadHole(ModelDoc2 model, Face2 face, double centerX, double centerY, string threadSize) { FeatureManager featMgr = model.FeatureManager; SelectionMgr selMgr = model.SelectionManager; // Step 1: 获取螺纹参数(简化版,实际应查GB表) double majorDiameter = threadSize switch { "M6" => 6.0, "M8" => 8.0, "M10" => 10.0, _ => throw new ArgumentException("不支持的螺纹规格") }; // Step 2: 创建沉头孔草图 SketchManager sketchMgr = model.CreateDrawnSketch2(face); sketchMgr.CreateCircle(centerX, centerY, 0, centerX + majorDiameter/2 + 1.0, centerY, 0); // 沉头直径 = 大径+2mm sketchMgr.CreateCircle(centerX, centerY, 0, centerX + majorDiameter/2, centerY, 0); // 螺纹底孔直径 = 大径 // Step 3: 拉伸切除沉头孔(深度=1.5×大径) object[] bodies = featMgr.FeatureCutEx2( true, // 薄壁 false, // 保持相交 false, // 合并实体 (int)swEndCondition_e.swEndCondUpToSurface, // 终止条件 0, // 深度 0, // 拔模角度 0, // 拔模方向 0, // 起始偏移 0, // 终止偏移 0, // 薄壁厚度 0, // 薄壁方向 0, // 薄壁拔模 0, // 薄壁拔模方向 0, // 薄壁起始偏移 0, // 薄壁终止偏移 0, // 薄壁拔模角度 0, // 薄壁拔模方向 0, // 薄壁起始偏移 0, // 薄壁终止偏移 0, // 薄壁拔模角度 0, // 薄壁拔模方向 0, // 薄壁起始偏移 0, // 薄壁终止偏移 0, // 薄壁拔模角度 0, // 薄壁拔模方向 0, // 薄壁起始偏移 0, // 薄壁终止偏移 0, // 薄壁拔模角度 0, // 薄壁拔模方向 0, // 薄壁起始偏移 0, // 薄壁终止偏移 0, // 薄壁拔模角度 0, // 薄壁拔模方向 0, // 薄壁起始偏移 0, // 薄壁终止偏移 0, // 薄壁拔模角度 0, // 薄壁拔模方向 0, // 薄壁起始偏移 0, // 薄壁终止偏移 0, // 薄壁拔模角度 0, // 薄壁拔模方向 0, // 薄壁起始偏移 0, // 薄壁终止偏移 0, // 薄壁拔模角度 0, // 薄壁拔模方向 0, // 薄壁起始偏移 0, // 薄壁终止偏移 0, // 薄壁拔模角度 0, // 薄壁拔模方向 0, // 薄壁起始偏移 0, // 薄壁终止偏移 0, // 薄壁拔模角度 0, // 薄壁拔模方向 0, // 薄壁起始偏移 ...... // 此处省略大量参数,实际需按API文档填满 ); // ⚠️ 关键:FeatureCutEx2参数极多,必须严格按顺序传入。推荐使用封装方法: // var cutFeat = featMgr.FeatureCut(true, false, false, 0, majorDiameter * 1.5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ............); // 但更推荐:先用宏录制,再提取参数序列 return true; }4.2.1 参数表:FeatureCutEx2关键参数含义(按SolidWorks API文档)
| 参数索引 | 参数名 | 典型值 | 说明 |
|---|---|---|---|
| 0 | Boss | true | 是否为凸台特征(false为切除) |
| 1 | From | swStartSketchPlane | 起始面类型 |
| 2 | Depth | 9.0 | 拉伸深度(M6时=6×1.5) |
| 3 | UpToSurface | null | 终止面(若为null则用深度) |
| 4 | FlipSideToCut | false | 是否反向切除 |
| 5 | Merge | true | 是否合并到主体 |
| 6 | UseFeatScope | false | 是否使用特征范围 |
| 7 | FeatScopeArray | null | 特征范围数组 |
提示:
FeatureCutEx2有58个参数,实际开发中建议用FeatureCut(简化版,仅12参数),或通过MacroRecorder录制操作后提取参数——这是最可靠的参数获取方式。
4.3 排错指南:重建失败的三大高频原因及验证方法
当调用model.EditRebuild3()后模型变空白或报错,按以下顺序排查:
| 现象 | 可能原因 | 验证方法 | 解决方案 |
|---|---|---|---|
| 重建后特征消失 | 草图未完全定义(欠约束) | 在SolidWorks中右键草图→“显示/删除几何关系”,检查是否标红 | 添加sketch.AddGeometricRelation2("Line1","Line2", (int)swDimensionType_e.swDimensionType_Perpendicular) |
| FeatureManager::FeatureCut返回null | 切除方向错误(如在实体内部创建负空间) | 用model.Extension.SelectByID2("Face1@Part1", "FACE", 0,0,0, false, 0, null, 0)手动选面验证 | 调整FlipSideToCut参数为true |
| 调用Thread时崩溃 | 未先创建圆柱面作为螺纹基体 | 在FeatureManager中查看特征树,确认存在圆柱面 | 先用FeatureManager::FeatureExtrude2创建圆柱,再在其面上调用FeatureThread |
终极验证法:在代码中插入日志输出当前状态:
// 输出当前活动文档类型和特征数 Debug.WriteLine($"文档类型: {model.GetType().Name}, 特征数: {model.FeatureCount}"); // 输出最后创建的特征名称 Feature lastFeat = model.FirstFeature(); while (lastFeat.GetNext() != null) lastFeat = lastFeat.GetNext(); Debug.WriteLine($"最后特征: {lastFeat.Name}");5. 进阶技巧:用PropertyManagerPage构建专业级交互界面
5.1 为什么不用WinForms而用PropertyManagerPage
WinForms窗体在SolidWorks中会遮挡模型视图,且无法响应SolidWorks的实时事件(如旋转模型时窗体不跟随)。PropertyManagerPage是SolidWorks原生UI框架,其优势在于:
- 深度集成:可嵌入SolidWorks属性管理器面板(右侧),与FeatureManager树同级;
- 事件驱动:支持
OnButtonPress、OnGroupExpand、OnSelectionBoxCallout等20+事件; - 智能选择:
SelectionBox控件可限定用户只能选择特定类型对象(如“仅平面”、“仅边线”); - 状态保持:关闭后自动保存用户输入,下次打开恢复上次值。
5.2 创建GB螺纹孔配置面板的完整流程
public class ThreadHolePMP : PropertyManagerPage2 { private SldWorks _swApp; private ModelDoc2 _model; private SelectionMgr _selMgr; public ThreadHolePMP(SldWorks swApp) { _swApp = swApp; _model = swApp.ActiveDoc; _selMgr = _model.SelectionManager; } public void Show() { // 创建PropertyManagerPage PropertyManagerPage2 pmp = _swApp.CreatePropertyManagerPage( "GB螺纹孔配置", (int)swPropertyManagerPageOptions_e.swPropertyManagerPageOptions_OkayButton | (int)swPropertyManagerPageOptions_e.swPropertyManagerPageOptions_CancelButton, this, null); // 添加选择框(仅允许选择平面) pmp.AddSelectionBox( "选择基准面", "请选择一个平面作为螺纹孔定位面", (int)swSelectType_e.swSelFACES, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ...... <p> <a href="https://download.csdn.net/download/weixin_42683392/27399368" style="color:#ec7500;font-size:14px;"> 本文还有配套的精品资源,点击获取 </a> <img alt="menu-r.4af5f7ec.gif" src="https://csdnimg.cn/release/wenkucmsfe/public/img/menu-r.4af5f7ec.gif" style="width:16px;margin-left:4px;vertical-align:text-bottom;cursor:text;"> </p>