恒美微站
首页
关于我们
建站服务
主题模板
案例展示
资讯中心
联系我们
SolidWorks API二次开发入门:C#环境搭建与第一个插件实战
首页
资讯中心
/
SolidWorks API二次开发入门:C#环境搭建与第一个插件实战
SolidWorks API二次开发入门:C#环境搭建与第一个插件实战
发布时间:2026/10/2 13:20:20
第一次接触SolidWorks API开发的人十有八九是被“二次开发”这个词吓住的。其实把话说白了SolidWorks API就是用代码去驱动SolidWorks这个软件让软件替你干那些重复得让人想摔鼠标的活儿——比如给几百个零件批量改名、自动生成工程图、按规则调整模型参数。C#是官方支持最好、社区资料最丰富的语言之一用C#写SolidWorks插件本质上就是调用一堆SDK接口去操作模型、属性、特征树这些东西。这篇文章我想写给两类人一类是SolidWorks用得挺熟、但没写过代码的机械工程师你想把手头重复工作自动化另一类是有C#基础、但对CAD领域完全陌生的软件开发者你想切入工业软件这个赛道。两类的学习路径不太一样但第一脚踩进去的时候遇到的坑几乎是同一批。这系列文章我会持续更新第一篇先解决“跑通第一个程序”的问题包括环境怎么搭、版本怎么选、第一行代码怎么写、最常见的报错怎么排查。不画大饼全部是我自己踩过的坑和验证过的方案。1. 环境搭建与版本匹配SolidWorks API的“第一道坑”很多人第一步就死在环境上。这不是代码的问题是SolidWorks API开发的特殊性——COM组件、互操作程序集、版本强绑定这三样东西凑在一起稍有闪失程序就跑不起来。1.1 版本选型VS、Framework和SolidWorks的三角关系SolidWorks API有一个原则API版本与SolidWorks主版本严格对应。你用SolidWorks 2019就找2019对应的Interop程序集用SolidWorks 2021就找2021的。跨版本调用通常不兼容经常遇到“无法加载DLL”或者“类未注册”的报错。我个人的建议是SolidWorks最好用2019以上的版本API更稳定官方文档也更完善Visual Studio2019或2022都行建议2019网上资料比较多遇到问题好搜.NET Framework4.6.1到4.8都可以SolidWorks API官方基于.NET Framework不是.NET Core/.NET 5互操作程序集在SolidWorks安装目录下的SolidWorks.Interop.sldworks.dll和SolidWorks.Interop.swconst.dll注意新一代SolidWorks API在某些新版本中开始支持.NET Core/.NET 6编写的插件但社区资料和实际项目的主流仍是.NET Framework。如果你是新手先别玩花的老老实实按上面的组合来。有个热词问“vs2019开发的c#上位机源码程序能用vs2015打开吗”答案是能打开但要看项目里用的语言特性和包版本。放到SolidWorks API里也一样——用VS2019创建的插件项目拿到VS2015里大概率编译不过因为项目文件格式和C#语言版本都变了。反过来VS2015的项目用VS2019打开基本没问题VS会自动升级项目格式。1.2 引用配置Embed Interop Types必须设为False首次创建项目建议选择“类库.NET Framework”模板。我见过很多新手用“控制台应用”来写SolidWorks API代码。这个问题在于SolidWorks API大量使用COM对象你在控制台里操作完了控制台程序退出后SolidWorks可能还留着COM引用的进程导致SolidWorks崩掉或者卡死。所以老老实实建一个Class Library类库项目这是我们做插件的基础形态。创建项目后马上要做两件事添加引用右键项目 → 添加 → 引用 → 浏览找到SolidWorks安装目录下的SolidWorks.Interop.sldworks.dll和SolidWorks.Interop.swconst.dll把两个引用的“Embed Interop Types”属性改为False。这个不做运行时会报“无法将类型为‘SolidWorks.Interop.sldworks.SldWorks’的对象强制转换为接口类型”的错误为什么必须改Embed Interop Types这个属性如果为True编译器会把COM类型嵌入到你的程序集里好处是不需要目标电脑装SolidWorks也能编译但它处理复杂的COM接口继承关系时经常出错。SolidWorks的API类型层级很深嵌入后类型转换特别容易翻车。设为False后程序直接引用外部COM组件类型转换的问题就少很多。// 最简启动代码连接已经打开的SolidWorks实例 using SolidWorks.Interop.sldworks; using SolidWorks.Interop.swconst; SldWorks swApp null; // 尝试获取正在运行的SolidWorks实例 swApp Marshal.GetActiveObject(SldWorks.Application) as SldWorks; if (swApp null) { // 如果没有运行中的实例就新建一个 swApp Activator.CreateInstance(Type.GetTypeFromProgID(SldWorks.Application)) as SldWorks; swApp.Visible true; }这段代码是SolidWorks API的“Hello World”后面所有开发都从这里开始。Marshal.GetActiveObject是COM编程里的经典方法用来获取系统中正在运行的COM对象实例。SolidWorks启动的时候会注册一个名为“SldWorks.Application”的COM实例我们拿到它就像拿到了遥控器。2. 从Hello World到能用的插件第一个SolidWorks API程序跑通连接后下一步是理解SolidWorks API的“套路”。这个套路一旦搞明白后面写什么功能都是同一套逻辑找到对象 → 调用方法 → 处理返回值。2.1 理解对象模型swApp、IModelDoc2与ModelDocExtensionSolidWorks API的对象模型很像一个公司的组织架构。最高层是SldWorks对象相当于老板什么都管往下是ModelDoc2模型文档相当于部门经理管着零件、装配体、工程图这些具体文档再往下是ModelDocExtension模型扩展相当于部门里的专项小组专门处理特征、属性、方程式这些复杂操作。刚开始写代码的时候你只需要盯住三个对象SldWorks全局入口负责打开文件、新建文档、获取当前活跃文档ModelDoc2代表当前打开的一个模型文档可以强制转换成PartDoc、AssemblyDoc、DrawingDocModelDocExtension处理大量进阶功能比如遍历特征、读取自定义属性、调用命令// 获取当前活跃的模型文档 ModelDoc2 swDoc swApp.ActiveDoc as ModelDoc2; if (swDoc null) { MessageBox.Show(请先打开一个零件或装配体); return; } // 获取文档路径 string filePath swDoc.GetPathName(); MessageBox.Show(当前文档路径 filePath);这里有个新手常见的困惑为什么先swApp.ActiveDoc as ModelDoc2而不是直接swApp.IActiveDoc2因为SolidWorks API里带“I”前缀的接口是“新接口”不带“I”的是兼容接口。官方文档上推荐用IActiveDoc2这种带I的但老代码里基本都是不带I的用as转换一下更安全。我个人的习惯是先用不带I的老接口遇到问题再切新的。swApp.ActiveDoc获取当前激活的模型注意可能返回null比如SolidWorks处于空闲状态时swDoc.GetPathName()获取文件的完整路径如果文档还没保存过返回空字符串swDoc.GetTitle()获取文档的名称2.2 写一个能“干活”的插件批量修改零件材质纯Hello World没什么用咱们直接上一个有实际价值的案例批量修改一个装配体下所有零件的材质属性。这个需求场景很典型——设计师接了个项目客户要求所有零件统一使用“6061铝合金”但几十个零件都是以前的老图纸材质属性参差不齐。手工改得一个个零件打开、右键材质、选类型没有半小时搞不定。用API写个插件几秒钟完事。核心思路遍历装配体里所有零件 → 对每个零件打开模型文档 → 设置材质属性 → 保存关闭。using SolidWorks.Interop.sldworks; using SolidWorks.Interop.swconst; public static void BatchSetMaterial(SldWorks swApp, string materialName) { ModelDoc2 swDoc swApp.ActiveDoc as ModelDoc2; if (swDoc null) return; // 遍历装配体里的所有引用文档 object[] docRefs swDoc.GetDocumentDependencies(true, true, true); foreach (object docRefObj in docRefs) { // 获取被引用的文档 ModelDocExtension ext (docRefObj as ModelDoc2).Extension; if (ext null) continue; string docType (docRefObj as ModelDoc2).GetType(); if (docType Part) { // 设置材质 bool success ext.SetMaterialPropertyName2( Default, materialName); if (success) Console.WriteLine((docRefObj as ModelDoc2).GetTitle() - 设置成功); } } }这段代码用了GetDocumentDependencies方法返回当前文档依赖的所有子文档——对装配体来说就是它包含的所有零件和子装配体。然后逐个判断是否是零件是零件就调SetMaterialPropertyName2设置材质。SetMaterialPropertyName2这个方法我用得很频繁第一个参数传“Default”代表默认配置第二个参数传材质名称。材质名称必须和SolidWorks材质库里的名称完全一致比如“6061 Aluminum Alloy.Alloy”或者“AISI 304 Stainless Steel.Alloy”否则设置不生效。注意GetDocumentDependencies返回的是object数组这是SolidWorks API的常态——它不喜欢强类型集合所有数组一律用object[]。开发的时候每个元素拿出来都要先转成对应的接口类型再调用方法这一步不做后面必然报错。3. C#语言储备哪些基础知识在API开发中最常用学SolidWorks API的过程中很多人发现自己不是卡在API理解上而是卡在C#基础上。考虑到标题里提到的不少C#热词我把API开发中最常用的C#知识点集中梳理一遍。3.1 委托与事件让插件学会“主动汇报”刚开始写插件的时候你可能会觉得“我调APIAPI给我返回结果”就够了。但实际开发中经常有反向需求SolidWorks里发生了一个操作比如用户选中了一个面、保存了一个零件你的插件怎么知道答案就是委托和事件。SolidWorks API有一整套通知机制允许你在特定“通知”上挂载处理函数。比如你想在用户每次保存文件时自动执行一段代码就需要注册“文件保存通知”// 定义委托对应SolidWorks通知的回调签名 private delegate void FileSaveNotifyHandler(); // 存储当前通知事件实例 private FileSaveNotifyHandler _fileSaveNotify; public void RegisterSaveNotification(SldWorks swApp) { // 创建通知事件 _fileSaveNotify new FileSaveNotifyHandler(OnFileSave); // 注册为SolidWorks通知 int notifyId swApp.SetAddinCallbackInfo2(0, this, 0); bool registered swApp.SetNotificationCallback(_fileSaveNotify.Method.Name); }这里用委托是为了把“回调方法”作为对象传递和管理起来。C#里的delegate说白了就是一个“方法的指针”你把一个方法名包装成委托对象系统才能把它注册给COM通知机制。事件则是委托的封装只不过事件只能从类内部触发外部只能订阅安全性和封装性更好。SolidWorks API开发里常说的“Addin”本质就是大量使用事件和委托来响应软件的各种动作。3.2 反射、数组与类型转换处理API返回的“神秘对象”你写SolidWorks API代码时最常打交道的数据类型是object和object[]。这个设计确实让习惯了强类型的C#开发者难受但既然是COM的遗留设计咱们就得学会应对。数组问题GetDocumentDependencies返回object[]GetViews返回object[]GetBodies返回object[]……几乎所有的多值返回都是object数组。处理的时候建议先用foreach (object item in objArray)遍历再逐个转换类型不要在foreach里直接强转容易抛异常。类型转换常见的转换场景是从object转成IModelDoc2、IFeature、IEntity。拿IEntity举例子它几乎每个特征都有各种查询方法都返回它// 获取当前选中的实体 object selObj swDoc.SelectionManager.GetSelectedObject6(1, -1); IEntity ent selObj as IEntity; if (ent ! null) { // 获取实体类型 swSelectType_e selType (swSelectType_e)ent.GetType(); }反射反射技术用得不算多但有一个场景很经典——插件启动时动态加载同目录下的依赖DLL或者读取自定义特性。比如你写了一个集成多个功能的插件框架想通过反射扫描所有带[SwTool]特性的类并自动注册到菜单var types Assembly.GetExecutingAssembly().GetTypes() .Where(t t.GetCustomAttributes(typeof(SwToolAttribute), true).Length 0); foreach (var t in types) { object instance Activator.CreateInstance(t); // 注册到菜单... }反射能够提升插件的扩展性但使用时要注意异常处理因为反射调用出错时是在运行期暴露编译器完全帮不上忙。3.3 多线程与上位机场景API调用必须在主线程标题里反复出现“上位机”这个词也有“C#多线程”“延时”这些热词。常写上位机的人习惯性地用async/await、Task.Run来处理耗时操作。但是SolidWorks API开发有一个铁律COM对象必须在创建它的线程上调用。准确说SolidWorks API对象是COM对象不是线程安全的。你开一个后台线程去调swApp.ActiveDoc轻则卡死重则崩溃。这跟C#普通类库的编程思维完全不一样。我遇到过最典型的翻车场景是写一个批量导入数据的插件数据量大处理起来耗时很长。我想当然地用了Task.Run去跑导入逻辑结果程序刚开始运行就报“正在调用其他线程中的COM对象”的错误。后来换了方案用System.Windows.Forms.Timer每200毫秒处理一条数据把长时间任务切成小片在主线程上跑问题就解决了。给新手一个建议任何时候都不要在Task.Run、Thread、BackgroundWorker里直接调用SolidWorks API。如果你确实需要做耗时操作比如网络请求、数据库查询把这些操作放在后台线程得到结果后再通过Invoke回到主线程执行API操作。// 错误示范后台线程直接调用API Task.Run(() { ModelDoc2 doc swApp.ActiveDoc as ModelDoc2; // 崩溃现场 }); // 正确做法后台拿数据主线程操作API string dataFromDb null; Task.Run(() { dataFromDb QueryDatabase(); // 后台查询数据库 }).ContinueWith(t { ModelDoc2 doc swApp.ActiveDoc as ModelDoc2; // 回到主线程执行 // 把数据库数据写入模型... }, TaskScheduler.FromCurrentSynchronizationContext());第二个示例里TaskScheduler.FromCurrentSynchronizationContext()保证了ContinueWith里的代码回到UI主线程执行这是WPF/WinForms环境下的标准做法。3.4 泛型与集合推荐使用List而非ArrayList前面说了SolidWorks API返回的是object[]但你自己组织数据时强烈建议用ListT而不是ArrayList。泛型集合不仅类型安全性能也更好而且配合LINQ查询非常舒服。// 收集装配体下所有零件名 Liststring partNames new Liststring(); object[] docRefs swDoc.GetDocumentDependencies(true, true, true); foreach (object docRef in docRefs) { if (docRef is ModelDoc2 model model.GetType() Part) { partNames.Add(model.GetTitle()); } } // 用LINQ查找特定零件 var targetParts partNames.Where(name name.Contains(外壳)).ToList();顺便说一下字符串操作。C#截取字符串的方法基本就那几个Substring、Split、Replace、IndexOfSolidWorks API开发里最常用的是Split和Replace。比如你要从D:\Projects\Part_A.SLDPRT里把文件名抠出来用Path.GetFileNameWithoutExtension比任何字符串截取都省事。这算是我写代码的一个习惯能交给框架处理的事情绝不自己造轮子。4. 调试技巧与常见问题排查实录写代码不调试是不可能的尤其SolidWorks API的调试体验比普通程序痛苦得多。比如你直接按F5启动调试SolidWorks会重新启动而且加载你这个还没编译好的插件搞不好就把SolidWorks搞崩了。下面是我总结的几条实操经验。4.1 连接不上的时候先查这五件事很多新手写完连接代码运行后发现swApp是null或者弹出一堆看不懂的COM错误。遇到这种情况优先检查下面五项检查项正确做法常见错误VS版本VS2019及以上用VS2015跑新项目格式SolidWorks版本2019及以上版本过老API接口缺失.NET Framework4.6.1–4.8用了.NET Core/C# 10Embed Interop Types设为False保持True导致类型转换异常管理员权限以管理员身份运行VS权限不足无法访问COM组件其中“以管理员身份运行VS”是个不显眼但很关键的点。SolidWorks安装时会在系统里注册COM组件这些注册表项有些默认不允许非管理员写入。你不是管理员身份运行VSCOM组件就注册不了连接自然失败。4.2 典型异常的排查思路异常1COMException拒绝访问看到这个错误百分之八十是权限问题。右键VS图标 → 以管理员身份运行。如果是部署给别人的插件需要在目标电脑上注册DLL用regasm或者在安装包里做。异常2尝试读取或写入受保护的内存大部分情况下是引用的COM对象已经释放了。SolidWorks API的很多方法返回的接口只是临时引用你存到变量里等一会儿再用那个COM对象可能已经被SolidWorks内部回收了。解决方案是尽快用完不要长时间保存引用。特别是遍历特征的时候遍历过程中删除了某个特征后面再访问已删除特征的引用就会触发这个错误。异常3未将对象引用设置到对象的实例这是个经典空引用错误。API方法返回null之后你还在它上面继续调方法。SolidWorks API里很多方法都有可能返回null比如swApp.ActiveDoc在文档关闭后就是nullGetFeatureByPosition找不到特征也返回null。写代码的时候要养成“方法调用后先判空”的习惯。我习惯在每一个API调用的后面都加上判空检查这习惯在SolidWorks API世界里尤其重要因为这个API有大量静默失败——方法调用不报错就是返回null你往下写就得崩溃。4.3 调试效率翻倍宏录制的妙用SolidWorks有一个被严重低估的功能——“宏录制”。你完全可以用“宏录制”来逆向工程API代码。原理是SolidWorks界面上的每个操作背后都是API调用。你录下“新建零件 → 插入一个长方体 → 添加材质”然后停止录制就能得到一份VBA版的API代码。把VBA代码转成C#来参考比自己翻文档找方法快好几倍。我之前写过一个“批量导出STEP”的插件完全不知道怎么调用导出功能。后来录制了一遍手动操作看到宏里录出来的swDoc.SaveAs带了一堆参数照着改改就搞定了。**新手练手时最有效的路径是先录制宏再对照翻译成C#再根据自己的需求修改。**这比从头翻官方文档高效得多。5. 新手入门路线图与进阶方向判断这篇文章是“新手引导一”写到这里我已经把环境搭建、第一个程序、C#基础应用和调试技巧都覆盖完了。最后聊聊后续怎么学以及往哪个方向深入的问题。5.1 入门路线按这个顺序学少走弯路我见过不少新手一上来就研究“如何写任务窗格”“如何添加自定义图标菜单”结果连模型遍历都没搞明白。基于我的经验建议按下面这个顺序推进第一阶段能连接SolidWorks、能操作当前模型会用模型文档属性标题、路径、名称第二阶段遍历零件、装配体和所有特征会修改模型属性、自定义属性第三阶段掌握选择管理器和标记能读取用户交互点击、框选第四阶段能创建、编辑草图能调用特征生成实体拉伸、旋转第五阶段集成通知事件做真正的Addin插件带菜单栏、工具栏、任务窗格第一到第三阶段用宏录制加代码修改就能搞定效率很高。第四阶段开始需要理解模型构建的原理工作量一下子大起来。第五阶段则开始考验软件工程能力比如插件卸载时的资源释放、多语言支持、版本兼容性测试。5.2 进阶方向从“能用”到“好用”的差距在哪很多人会写API了之后发现自己的工具跟商用的SolidWorks插件比差距还是很明显。差距主要在三块第一用户界面。专业的SolidWorks插件大多有任务窗格Task Pane用WPF做复杂的树形结构、数据表格还能实时联动。这部分需要的是WPF技能跟SolidWorks API本身关系不大。第二稳定性。工业场景里插件处理一万个零件时不能卡死不能崩遇到错误要能自动跳过并记录日志。这就涉及到异常处理、事务回滚、批量性能优化。第三业务逻辑。API只是工具真正值钱的是你对工艺的理解、对设计规范的掌握。比如自动出工程图的插件表面上看是调用API标注尺寸实际上是你得知道哪些尺寸该标、标注放在哪里符合国标。业务知识的积累比技术细节更花时间。如果你打算用SolidWorks API做副业接单或者跳槽到工业软件公司我的建议是CS基础别丢尤其是设计模式、数据结构、WPF界面开发这三块。同时多到机械设计现场看流程理解真实的业务痛点才能真正做出有市场价值的工具。写在最后几个让我印象深刻的实战体会写到这里第一期新手引导差不多该收尾了。最后分享几个让我印象深刻的实战体会希望对刚开始学SolidWorks API的人有用。第一个体会是别怕报错。SolidWorks API的报错信息不够友好“未将对象引用设置到对象的实例”这个错误我在写API的第一年见过几百次。后来心态放平了只要报空引用第一反应就是“哪个API返回了null”顺着调用链查下去基本都能定位。第二个体会是勤用宏录制。我到现在写不熟悉的API功能时还是会先录一遍宏看看SolidWorks自己是怎么调的。宏代码虽然啰嗦但它是最真实的API调用范例比任何文档都靠谱。第三个体会是版本管理要趁早。API项目很容易出现“在我电脑上跑得好好的到客户那边就打不开”的尴尬。尽早把SolidWorks版本、VS版本、.NET Framework版本这几个变量固定下来写进项目说明文档能省掉后面无数沟通成本。最后想说的是SolidWorks API开发确实有门槛但并不是不可逾越的。它不像算法那么烧脑也不像底层驱动那么玄学本质上就是“理解对象模型 熟悉API方法 掌握C#基础”这三件事的组合。如果这篇文章能帮你把环境跑通、代码跑起来那它就算完成使命了。下一期我会重点讲模型遍历和特征操作这是做批量自动化必须啃下的硬骨头。到时见。