ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

C# SOLIDWORKS工程图标注自动化:从选边到插尺寸的完整实践

C# SOLIDWORKS工程图标注自动化:从选边到插尺寸的完整实践 简介这是面向机械设计工程师和CAD二次开发者的C#自动化标注示例用于解决SOLIDWORKS工程图手动标注耗时、易错的问题。资源共115个文件压缩包仅1.9MB包含C#源码工程sln、csproj、工程图/零件/装配模板drwdot、prtdot、asmdot及运行所需的dll和界面图标png等便于直接编译或对照学习。示例基于.NET Framework 4.8与SOLIDWORKS 2022 SP5.0通过SDK编程调用API实现尺寸标注、公差标注和注释添加等关键操作并附有相关配置与说明文件能帮助读者快速搭建自己的标注自动化插件减少重复劳动、保证标注一致性。已有583人浏览学习适合需要提升出图效率的研发设计人员参考实践。1. C# 给 SOLIDWORKS 工程图做标注自动化这套示例先帮你把最麻烦的选边和插尺寸打通现实里工程图标注自动化最难的不是写循环而是搞清 SOLIDWORKS 把「尺寸」「注释」「形位公差」藏在了哪些接口背后。这套基于 C# 的 SOLIDWORKS 工程图标注自动化示例目标就是把工程图文档里重复的标注工作比如补尺寸、加粗糙度、插形位公差封装成能直接调用的函数。它把连接 SOLIDWORKS、打开图纸、遍历视图、选择边线、插入标注的完整链路拆成了独立步骤非常适合懂制图规范、会一点 C#、但没系统看过 SOLIDWORKS API 的工程师。我拿到这类项目会先只盯两个点怎么选中目标边线怎么把尺寸插进去并且不弹出输入框。这两步通了整个自动化就立住了一大半。2. 先拆对象模型哪些标注能自动化哪些该留给模板2.1 工程图标注背后对应的 COM 对象DIM、GTOL、粗糙度与注释SOLIDWORKS 的 API 把工程图里的标注都包装成 COM 对象但每种对象的创建入口完全不同。尺寸对应IDimension注释对应IAnnotation形位公差对应IGtol表面粗糙度对应ISurfaceFinish。这四类接口都挂在 Document 对象下面可创建方式不是一个统一的InsertAnnotation就能覆盖的。从自动化难度来看普通的线性尺寸和直径尺寸最简单因为它的位置和方向都能用坐标描述注释次之麻烦在引线锚点和文本换行形位公差和粗糙度难度最高因为除了放置坐标还要设置符号类型、公差值、基准标识、复合框参数一多就容易出边界问题。实际工程里我见过不少半成品插件能把尺寸刷出来但粗糙度符号位置完全不挨着边线最后还得人工一个个拖回去。标注类型主要接口创建难度典型参数线性/直径尺寸IDimension低位置、方向、延伸线注释IAnnotation中文本、样式、附着点形位公差IGtol高符号、公差、基准、框体表面粗糙度ISurfaceFinish高符号类型、数值、方向这套示例帮你省掉的最重要工作量就是把这四类对象的参数整理成了 C# 的可读结构而不是让你对着 API 文档猜数值。2.2 示例项目的代码组织方式拿到源码先看哪几个文件一个正经的 C# 工程图自动化项目不会把所有逻辑塞进一个Program.cs。拿到这套示例时我建议先看入口和控制类不要一头扎进底层 API 封装里。文件/类职责阅读优先级Program.cs程序入口演示单张图纸标注流程最高SwConnector.cs连接 SOLIDWORKS 进程、打开文档高DrawingWalker.cs遍历图纸和视图返回视图列表高AnnotationHelper.cs封装尺寸、注释、形位公差、粗糙度插入中BatchRunner.cs批量处理多张工程图管理日志低后期再用我的习惯是先看Program.cs里有几行核心调用再看AnnotationHelper里有没有处理「输入尺寸值」弹窗。如果示例里没处理弹窗你第一轮跑多半会卡在某个图纸上。2.3 边界判断模板能解决的不要写脚本这套示例能自动插入标注不代表所有标注都应该由脚本完成。标题栏、技术要求、图框这些固定内容应该用图纸模板或者属性卡驱动脚本去生成纯属浪费维护成本。真正值得自动化的是那些随模型几何变化的尺寸、批量重复的孔标注、以及必须对应到具体边线的粗糙度和形位公差。另一个边界是「关联性」。脚本插入的尺寸如果只是画在图纸上、和模型几何没有关联那就是死尺寸模型一改它不会跟着动这在交付图纸时是重大隐患。所以每次插入尺寸后要确认返回的对象确实属于视图下的模型尺寸而不是注释型尺寸。这也是判断一个标注自动化示例能不能用的核心标准。3. 搭建环境与连接处理C# 拿到 SOLIDWORKS 文档对象才算开始3.1 引用 Interop DLL版本匹配与“嵌入互操作类型”开关SOLIDWORKS 二次开发第一坑永远是引用。示例大概率也是从SOLIDWORKS.Interop.sldworks.dll和SOLIDWORKS.Interop.swconst.dll开始。这两个 DLL 在 SOLIDWORKS 安装目录下的api\redist文件夹里不同主版本对应的 CLSID 基本兼容但接口新增的方法会不同。我建议用你本机版本对应的 DLL不要从网上随意拷一个。在 Visual Studio 里添加引用后必须把引用属性里的“嵌入互操作类型”改成False。如果保持默认的TrueCOM 接口封送时可能出现类型不匹配典型表现是运行时能连上 SOLIDWORKS但调用具体接口时抛InvalidCastException。平台目标也建议直接设为 x64和你的 SOLIDWORKS 位数保持一致避免 AnyCPU 在 64 位环境里出现奇怪的封送问题。3.2 连接已运行的 SOLIDWORKS先用 GetActiveObject失败再启动新实例工程图自动化最稳妥的连接方式是复用已经打开的 SOLIDWORKS 实例这样能看到运行过程也方便调试。获取当前实例需要借助 OLE 的GetActiveObject。示例里一般封装成这样的函数[DllImport(ole32.dll)] static extern int GetActiveObject(string progId, out object obj); private static SldWorks ConnectOrStartSw() { object oleObj null; try { GetActiveObject(SldWorks.Application, out oleObj); } catch { oleObj null; } SldWorks swApp oleObj as SldWorks; if (swApp null) { Type swType Type.GetTypeFromProgID(SldWorks.Application); swApp (SldWorks)Activator.CreateInstance(swType); swApp.Visible true; } return swApp; }这段代码的逻辑很直接先尝试拿到已存在的 COM 对象没有就创建一个新实例。注意Activator.CreateInstance之后把Visible设为true否则程序可能在后台无界面启动遇到弹窗时你根本看不到误以为卡死。实际批处理阶段一般会反过来把Visible设为false减少窗口资源占用。3.3 打开工程图OpenDoc6 与静默模式参数拿到SldWorks对象后下一步是打开.slddrw文件。标准做法是OpenDoc6它的返回值是一个ModelDoc2对象可以向下转型成DrawingDoc。这里最容易翻车的是第四个参数也就是打开选项里的静默模式。int error 0; int warning 0; ModelDoc2 model swApp.OpenDoc6( filePath, (int)swDocumentTypes_e.swDocDRAWING, (int)swOpenDocOptions_e.swOpenDocOptions_Silent, , ref error, ref warning); if (model null) { Console.WriteLine($打开失败: {filePath}, error{error}, warning{warning}); return null; } DrawingDoc drawing (DrawingDoc)model;参数说明swDocDRAWING告诉 API 这是工程图类型swOpenDocOptions_Silent表示静默打开不弹任何对话框。如果没有加这个选项当图纸引用了缺失的模型文件时SOLIDWORKS 会弹出一个模态对话框批处理脚本很可能会卡在那里等用户点确认。error和warning一定要传变量进去打开失败后能看到具体错误码。比如error2通常和文件格式或版本有关error11一般是文件被占用。3.4 遍历图纸和视图GetViews 返回的 object[] 要小心处理工程图可以有多张图纸每张图纸里又有多个视图。SOLIDWORKS API 里有个比较反直觉的设计DrawingDoc.GetViews()返回的是object[]里面每个元素其实是View对象。直接强转容易出问题尤其是数组里偶尔混入空引用。private static ListView GetAllViews(DrawingDoc drawing) { ListView views new ListView(); int sheetCount drawing.GetSheetCount(); for (int i 0; i sheetCount; i) { drawing.SetCurrentSheet(i); object[] rawViews drawing.GetViews(); if (rawViews null) continue; foreach (object rawView in rawViews) { View view rawView as View; if (view null || string.IsNullOrEmpty(view.GetName2())) continue; views.Add(view); } } return views; }这里先SetCurrentSheet(i)切到第 i 张图纸再取视图否则你拿到的视图列表可能只是第一张图纸的。GetName2()是获取视图名称的常见方法不同版本名称略有差异示例里一般会用这个来判断是不是目标视图。过滤逻辑很关键图纸里有些辅助视图、剖面视图是自动生成的你不一定想给它们插标注。环境搭建完成后大部分问题集中在 COM 对象释放上。这里有个血泪经验不要到处调用Marshal.ReleaseComObject在循环里频繁释放同一个对象很容易触发 Access Violation。这一点在后面的避坑章节展开。4. 核心标注实现尺寸、注释、粗糙度与形位公差的插入顺序4.1 选边和选面所有标注都依赖 SelectByID2在工程图里插标注SOLIDWORKS 的套路和手动操作一样先选中目标边线或面再执行标注命令。API 对应的是ModelDocExtension.SelectByID2。bool SelectEdge(DrawingDoc drawing, string viewName, string edgeName) { string fullName ${edgeName}{viewName}; ModelDoc2 model (ModelDoc2)drawing; return model.Extension.SelectByID2( fullName, EDGE, 0, 0, 0, false, 0, null, 0); }参数拆解第一个参数是选择对象的完整名称格式通常是Edge1视图名第二个参数EDGE表示选择类型也可以是FACE、VERTEX、DIMENSION后面三个坐标参数 0, 0, 0 是选择位置的近似坐标名称足够精确时这三个值无所谓。倒数第四个参数false表示不增加新的选择条目也就是先清空再选。返回值是bool很多新手不看这个返回值结果后续插入尺寸时操作的是空的选集命令静默失败。注意选择时务必确认视图没有被折叠或者隐藏。如果视图不可见SelectByID2大概率返回false。遇到这种情况先遍历视图判断view.Visible属性。4.2 插入线性尺寸CreateDimension2 的坐标与方向参数选好边线后插入智能尺寸最常见的 API 是DrawingDoc.CreateDimension2。示例里通常封装成这样internal static bool InsertLinearDimension( DrawingDoc drawing, string viewName, string edgeName, double textX, double textY, double textZ) { if (!SelectEdge(drawing, viewName, edgeName)) return false; Feature dimFeature drawing.CreateDimension2( textX, textY, textZ, 0, 0, 1, 0, 0, 0); if (dimFeature null) { Console.WriteLine($尺寸插入失败: {edgeName}); return false; } IDimension dim dimFeature.GetSpecificFeature2() as IDimension; return dim ! null; }CreateDimension2的前三个参数是尺寸文字放置位置的世界坐标单位是米注意不是图面单位这是最常见的位置漂移根源。中间三个参数是尺寸法向方向0,0,1表示垂直于工程图平面一般不变。最后三个参数是尺寸方向向量传全零表示让 SOLIDWORKS 根据所选边线自动判断方向。不同 SOLIDWORKS 版本对CreateDimension2的签名略有差异。如果编译不过打开对象浏览器看一下当前 Interop 版本的定义参数少一个或顺序变一下都很正常。核心思想不变位置坐标用米方向和延伸线尽量交给 API 自动判断让 SOLIDWORKS 去套用当前图纸样式的尺寸属性。4.3 注释、粗糙度与形位公差以宏录制为基准参数来源尺寸之外的三类标注API 调用参数非常繁琐我不建议对着文档硬啃。最快的方法是打开 SOLIDWORKS 宏录制手动插入一个粗糙度符号或者形位公差停止录制后看生成的 VBA 调用。这套示例的底层多半也是这么反推出来的。注释的插入相对简单可以用InsertAnnotation2IAnnotation note model.InsertAnnotation2( 技术要求未注圆角 R1, // 文本 0, // 样式 0, // 标志 0, // 固定角度 0.05, 0.05, 0.0); // 位置单位米形位公差和粗糙度就不适合在这里贴完整代码因为不同版本方法名从InsertGtol1到InsertGtol3都有。我的习惯是用宏录制抓出本机可用的调用再把参数改成从配置文件读取。示例项目里一般也会提供类似AnnotationHelper.InsertGtol(...)的封装内部参数列表很长但调用方只需要传符号、公差值、基准和坐标。4.4 按视图批量标注循环中提前关掉弹窗和输入框批量给多个视图插尺寸时最让人崩溃的不是代码逻辑而是 SOLIDWORKS 每到插入尺寸就会弹出“修改尺寸值”对话框。手动操作时这个对话框很方便脚本自动化时就是灾难经常有几百张图跑着跑着停在某个尺寸输入框上等人点确认。解决方案是在程序开始前关闭尺寸输入相关设置swApp.SetUserPreferenceToggle( (int)swUserPreferenceToggle_e.swInputDimValOnCreate, false);这行代码的意思是创建尺寸时不弹出输入值对话框直接用默认值。跑完整个流程再把它恢复成true。另一处要关的是“显示草图尺寸”之类和标注无关的弹窗它们同样会阻断批处理。循环遍历视图时还要注意视图方向。工程图里剖面视图、局部放大图的方向可能和主视图不一致如果示例的尺寸方向自动判断逻辑不够健壮插入的尺寸线方向会歪。所以批量前一定要先打印视图名称和视图类型人工过一遍哪些视图不该被自动标注。5. 避坑与排查标注自动化最容易翻车的 5 个现场5.1 现象标注位置随机漂移甚至跑到图纸外面现象脚本跑完尺寸文字没有靠近边线有的跑到图框外有的堆叠在一起。原因最常见的是单位不匹配。CreateDimension2的坐标单位是米而图纸里的视觉坐标往往用毫米另外视图在图纸上的位置有平移脚本如果直接用了模型坐标没有换算成图纸坐标尺寸就会随视图比例和位置整体偏移。解决先统一单位。从drawing.GetCurrentSheet()拿到图纸属性确认图纸单位是毫米再在封装层把输入坐标除以 1000 转成米。位置换算公式用视图的Position加视图比例系数不要自己瞎猜。跑完一张图立刻打开检查一个尺寸位置确认后写个单元测试锁住这个换算关系后续改代码也不会破坏。5.2 现象API 插入的尺寸值不对或出现过定义标注现象尺寸插进去了但值显示的是错的比如直径标注成了半径或者文档出现红色过定义提示。原因选择边线时选到了隐藏线、构造线或参考边SOLIDWORKS 按错误的几何计算尺寸值。更常见的是原图纸上已经有相同边线的尺寸脚本没检查直接再插一条导致重复标注和过定义。解决插入前先做一次“重复检测”。遍历当前视图已有的IDimension读它的GetReferenceEntity拿关联边线和本次要选的边线名比对。另外在选择参数里加上false的“选择隐藏边线”选项SOLIDWORKS 的SelectByID2有几个标志位可以控制排除隐藏边线。不要试图用删除再插入来解决那样会破坏原图纸已经调好的制图规范。5.3 现象调用崩溃报 Access ViolationC0000005现象程序运行到某个标注插入时直接崩溃事件查看器里能看到Access violation reading location 0x...错误码通常带c0000005。原因绝大多数情况是 COM 对象生命周期管理过头。很多人学了一招Marshal.ReleaseComObject就在循环里对同一个View或Dimension反复释放结果指针变成悬挂指针下一轮循环再去访问就崩了。另一个诱因是把“嵌入互操作类型”设为True导致接口封送后的运行时 RCW 被提前回收。解决不要到处手动释放 COM 对象。把获取到的SldWorks、DrawingDoc、View交给 .NET 的垃圾回收器或者只在合适的时机用一次Marshal.FinalReleaseComObject。设置完引用后检查 Interop DLL 的“嵌入互操作类型”确实是False。如果崩溃发生在极快速连续操作时可以在每张图纸处理完后调用GC.Collect()和GC.WaitForPendingFinalizers()但这只能算临时手段根治还是控制持有的 COM 引用数量。5.4 现象SOLIDWORKS 崩或提示“可用窗口资源极低”现象批量跑到几十张图纸后SOLIDWORKS 变慢鼠标转圈然后提示“可用窗口资源极低”再继续就未响应。原因工程图自动化过程中每次选择、插入标注都可能创建新的 COM 对象和 UI 窗口句柄。如果脚本没有在每张图纸处理完后释放文档甚至没有关闭文档撑到后面把系统的 User32 窗口资源耗尽。另一个常见原因是反复开关文档却不真正关闭导致内存中积累大量图纸对象。解决每处理完一张图纸执行CloseDoc把图纸关掉让 SOLIDWORKS 释放图形资源。批处理时把swApp.Visible设为false减少窗口句柄开销。如果仍然出现资源低检查是不是有宏或插件在跑后台任务把系统里不相关的 SOLIDWORKS 实例全关掉只留一个进程。还有个小技巧循环里的SelectionManager要清空选中状态卡在选集缓存里的对象不会自动释放。5.5 现象批处理很快就结束但工程图一张都没改现象日志显示每张图纸都“处理成功”但打开文件一看该插的标注一个都没有或者只有第一张改了。原因最常见的是OpenDoc6的静默模式打开的是已有实例里已经打开着的同名文档脚本拿到的ModelDoc2指向的是缓存里的旧版本文档插入操作被 SOLIDWORKS 当成只读或者被文档锁定API 直接返回空对象但脚本没检查继续跑。另一个原因是SelectByID2选边失败静默返回false封装函数直接吐了个false但上层没判断。解决在每个关键步骤后检查返回值并写入日志。尤其是SelectByID2失败时立刻输出当前视图名和边线名方便定位是哪张图纸的哪个视图出了问题。打开文档前用GetOpenDoc2查一下文件是否已在内存中是的话先CloseDoc再重开。最后批处理里加一个“预期标注数”的校验处理完统计实际标注数和预期对不上就标记为失败而不是只记一句“成功”。6. 把示例改造成批处理脚本日志、验证和可回滚的流程这套示例最大的价值不是单张图纸演示而是它能被扩展成批处理工具。我的改造思路是先做一次 dry-run再跑真正的批量任务。string[] files Directory.GetFiles(inputFolder, *.slddrw); foreach (string file in files) { var result ProcessDrawing(file, dryRun: true); Console.WriteLine(${Path.GetFileName(file)} - {result.Status}); }dryRun模式下打开图纸、遍历视图、执行所有SelectByID2但CreateDimension2之前只打印坐标和边线名不真正插入。这轮跑完我至少能确认所有视图名、边线名都是对的避免在正式批量时造出一堆错误标注再一张张撤销。正式批量时加一个配置文件控制参数比如尺寸样式、粗糙度数值、形位公差基准不要把这些硬编码在 C# 里。保存策略上永远不要直接用原文件保存。处理完后先另存到临时目录人工抽检两张再决定要不要覆盖原图。换句话说把“后悔药”做在流程里而不是依赖 SOLIDWORKS 的撤销栈。从那以后我每次给工程图跑自动化前都强制自己先走一遍单张图纸的 dry-run确认方向和位置没问题再放开批量这个习惯已经帮我挡掉了至少三波返工事故。这个示例项目最适合的用法正是把这个验证流程和你的图纸规范融合到一起。希望帮到你。本文还有配套的精品资源点击获取
返回列表